Problem Rikka with Sequence
题目大意
维护一个序列,支持三种操作。
操作1:区间加。 操作二:区间开根号(向下取整)。 操作3:区间求和。
解题分析
可以发现经过若干次操作后,整些区间内的数会趋向于相同。
可以再开一个标记,表示这个区间内的数是否相同,这样可以优化一下区间开根号的复杂度。
然后就卡过去了~~
Pushdown的时候要注意不要把一个lazy标记往下传两次。
参考程序
#include <cstdio>
#include <cmath> #define maxn 200008
#define lson l , m , rt << 1
#define rson m+1 , r , rt << 1 | 1
#define eps 1e-8
long long sum[maxn << ],lazy[maxn << ];
long long tag[maxn << ];
int n; void Pushup(int rt){
sum[rt] = sum[rt << ] + sum[rt << | ];
if (tag[rt << ] == tag[rt << | ]) tag[rt]=tag[rt << ]; else tag[rt] = ;
} void Pushdown(int rt,int m){
if (tag[rt]){
tag[rt << ] = tag[rt];
tag[rt << | ] = tag[rt];
sum[rt << ] = tag[rt] * (m-m/);
sum[rt << | ] = tag[rt] * (m/);
lazy[rt]=;
}
if (lazy[rt]) {
lazy[rt << ] += lazy[rt];
lazy[rt << | ] += lazy[rt];
sum[rt << ] += lazy[rt] * (m - m / );
sum[rt << | ] += lazy[rt] * (m / );
if (tag[rt << ]) tag[rt << ] += lazy[rt];
if (tag[rt << | ]) tag[rt << | ] += lazy[rt];
lazy[rt] = ;
}
} void Build(int l,int r,int rt){
lazy[rt] = ;
tag[rt] = ;
if (l==r) {
scanf("%d",&sum[rt]);
tag[rt]=sum[rt];
return;
}
int m = (l + r) >> ;
Build(lson);
Build(rson);
Pushup(rt);
} void Update(int L,int R,int val,int l,int r,int rt){
if (L <= l && r <= R) {
sum[rt] += 1ll*(r - l + ) * val;
lazy[rt] += val;
if (tag[rt]) tag[rt]+=val;
return;
}
Pushdown(rt,r - l + );
int m = (l + r) >> ;
if (L <= m) Update(L,R,val,lson);
if (m < R) Update(L,R,val,rson);
Pushup(rt);
} void Update_2(int L,int R,int l,int r,int rt){
if (L<=l && r<=R && tag[rt]){
tag[rt] = (long long)(sqrt(tag[rt])+eps);
sum[rt] = 1ll*tag[rt] * (r - l + );
return;
}
Pushdown(rt,r - l + );
int m = (l + r) >> ;
if (L <= m) Update_2(L,R,lson);
if (m < R) Update_2(L,R,rson);
Pushup(rt);
} long long Query(int L,int R,int l,int r,int rt){
if (L <= l && r <= R) {
return sum[rt];
}
Pushdown(rt,r - l + );
int m = (l + r) >> ;
long long res = ;
if (L <= m) res += Query(L,R,lson);
if (m < R) res += Query(L,R,rson);
return res;
} int main() {
int T;
scanf("%d",&T);
while (T--){
int Q;
scanf("%d %d",&n,&Q);
Build(,n,);
while (Q--) {
int x,y,z,w;
scanf("%d",&w);
if (w==) {
scanf("%d%d%d",&x,&y,&z);
Update(x,y,z,,n,);
}
if (w==){
scanf("%d%d",&x,&y);
Update_2(x,y,,n,);
}
if (w==){
scanf("%d%d",&x,&y);
printf("%I64d\n",Query(x,y,,n,));
}
}
}
}