Problem Rikka with Sequence
题目大意
维护一个序列,支持三种操作。
操作1:区间加。 操作二:区间开根号(向下取整)。 操作3:区间求和。
解题分析
可以发现经过若干次操作后,整些区间内的数会趋向于相同。
可以再开一个标记,表示这个区间内的数是否相同,这样可以优化一下区间开根号的复杂度。
然后就卡过去了~~
Pushdown的时候要注意不要把一个lazy标记往下传两次。
参考程序
1 #include <cstdio> 2 #include <cmath> 3 4 #define maxn 200008 5 #define lson l , m , rt << 1 6 #define rson m+1 , r , rt << 1 | 1 7 #define eps 1e-8 8 long long sum[maxn << 2],lazy[maxn << 2]; 9 long long tag[maxn << 2]; 10 int n; 11 12 void Pushup(int rt){ 13 sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; 14 if (tag[rt << 1] == tag[rt << 1 | 1]) tag[rt]=tag[rt << 1]; else tag[rt] = 0; 15 } 16 17 void Pushdown(int rt,int m){ 18 if (tag[rt]){ 19 tag[rt << 1] = tag[rt]; 20 tag[rt << 1 | 1] = tag[rt]; 21 sum[rt << 1] = tag[rt] * (m-m/2); 22 sum[rt << 1 | 1] = tag[rt] * (m/2); 23 lazy[rt]=0; 24 } 25 if (lazy[rt]) { 26 lazy[rt << 1] += lazy[rt]; 27 lazy[rt << 1 | 1] += lazy[rt]; 28 sum[rt << 1] += lazy[rt] * (m - m / 2); 29 sum[rt << 1 | 1] += lazy[rt] * (m / 2); 30 if (tag[rt << 1]) tag[rt << 1] += lazy[rt]; 31 if (tag[rt << 1 | 1]) tag[rt << 1 | 1] += lazy[rt]; 32 lazy[rt] = 0; 33 } 34 } 35 36 void Build(int l,int r,int rt){ 37 lazy[rt] = 0; 38 tag[rt] = 0; 39 if (l==r) { 40 scanf("%d",&sum[rt]); 41 tag[rt]=sum[rt]; 42 return; 43 } 44 int m = (l + r) >> 1; 45 Build(lson); 46 Build(rson); 47 Pushup(rt); 48 } 49 50 void Update(int L,int R,int val,int l,int r,int rt){ 51 if (L <= l && r <= R) { 52 sum[rt] += 1ll*(r - l + 1) * val; 53 lazy[rt] += val; 54 if (tag[rt]) tag[rt]+=val; 55 return; 56 } 57 Pushdown(rt,r - l + 1); 58 int m = (l + r) >> 1; 59 if (L <= m) Update(L,R,val,lson); 60 if (m < R) Update(L,R,val,rson); 61 Pushup(rt); 62 } 63 64 void Update_2(int L,int R,int l,int r,int rt){ 65 if (L<=l && r<=R && tag[rt]){ 66 tag[rt] = (long long)(sqrt(tag[rt])+eps); 67 sum[rt] = 1ll*tag[rt] * (r - l + 1); 68 return; 69 } 70 Pushdown(rt,r - l + 1); 71 int m = (l + r) >> 1; 72 if (L <= m) Update_2(L,R,lson); 73 if (m < R) Update_2(L,R,rson); 74 Pushup(rt); 75 } 76 77 long long Query(int L,int R,int l,int r,int rt){ 78 if (L <= l && r <= R) { 79 return sum[rt]; 80 } 81 Pushdown(rt,r - l + 1); 82 int m = (l + r) >> 1; 83 long long res = 0; 84 if (L <= m) res += Query(L,R,lson); 85 if (m < R) res += Query(L,R,rson); 86 return res; 87 } 88 89 90 int main() { 91 int T; 92 scanf("%d",&T); 93 while (T--){ 94 int Q; 95 scanf("%d %d",&n,&Q); 96 Build(1,n,1); 97 while (Q--) { 98 int x,y,z,w; 99 scanf("%d",&w); 100 if (w==1) { 101 scanf("%d%d%d",&x,&y,&z); 102 Update(x,y,z,1,n,1); 103 } 104 if (w==2){ 105 scanf("%d%d",&x,&y); 106 Update_2(x,y,1,n,1); 107 } 108 if (w==3){ 109 scanf("%d%d",&x,&y); 110 printf("%I64d ",Query(x,y,1,n,1)); 111 } 112 } 113 } 114 }