Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:
Yuta has an array A with n numbers. Then he makes m operations on it.
There are three type of operations:
1 l r x : For each i in [l,r], change A[i] to A[i]+x
2 l r : For each i in [l,r], change A[i] to ⌊√A[i]⌋
3 l r : Yuta wants Rikka to sum up A[i] for all i in [l,r]
It is too difficult for Rikka. Can you help her?
Input
The first line contains a number t(1<=t<=100), the number of the testcases. And there are no more than 5 testcases with n>1000.
For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation.
It is guaranteed that 1<=A[i],x<=100000.
Output
For each operation of type 3, print a lines contains one number -- the answer of the query.
Sample Input
1
5 5
1 2 3 4 5
1 3 5 2
2 1 4
3 2 4
2 3 5
3 1 5
Sample Output
5
6
题意
实现区间加,区间开根,区间求和
题解
一开始以为可以暴力开根,然后统计区间内是否全为1,后来发现开完根再加又可以开根所以单次复杂度就变成O(n)
后来发现区间开根会出现一大片相同的区域,所以可以再维护一个最大最小值,如果maxx[rt]-minn[rt]==(LL)sqrt(maxx[rt])-(LL)sqrt(minn[rt])||maxx[rt]==minn[rt]就说明区间开根后所有值都相同,那就可以直接更新区间
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 #define LL long long 5 6 const int maxn=1e5+5; 7 8 LL sum[maxn<<2],lazy[maxn<<2],minn[maxn<<2],maxx[maxn<<2]; 9 10 void pushdown(int l,int r,int rt) 11 { 12 if(lazy[rt]==0)return; 13 lazy[rt<<1]+=lazy[rt]; 14 lazy[rt<<1|1]+=lazy[rt]; 15 int mid=(l+r)>>1; 16 sum[rt<<1]+=lazy[rt]*(mid-l+1); 17 sum[rt<<1|1]+=lazy[rt]*(r-mid); 18 maxx[rt<<1]+=lazy[rt]; 19 maxx[rt<<1|1]+=lazy[rt]; 20 minn[rt<<1]+=lazy[rt]; 21 minn[rt<<1|1]+=lazy[rt]; 22 lazy[rt]=0; 23 } 24 void pushup(int rt) 25 { 26 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 27 minn[rt]=min(minn[rt<<1],minn[rt<<1|1]); 28 maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]); 29 } 30 void build(int l,int r,int rt) 31 { 32 lazy[rt]=0; 33 if(l==r) 34 { 35 scanf("%lld",&sum[rt]); 36 minn[rt]=maxx[rt]=sum[rt]; 37 return; 38 } 39 int mid=(l+r)>>1; 40 build(l,mid,rt<<1); 41 build(mid+1,r,rt<<1|1); 42 pushup(rt); 43 } 44 void update(int L,int R,LL C,int l,int r,int rt) 45 { 46 if(L<=l&&r<=R) 47 { 48 lazy[rt]+=C; 49 sum[rt]+=(r-l+1)*C; 50 maxx[rt]+=C; 51 minn[rt]+=C; 52 return; 53 } 54 int mid=(l+r)>>1; 55 pushdown(l,r,rt); 56 if(L<=mid)update(L,R,C,l,mid,rt<<1); 57 if(R>mid)update(L,R,C,mid+1,r,rt<<1|1); 58 pushup(rt); 59 } 60 void Sqrt(int L,int R,int l,int r,int rt) 61 { 62 if(L<=l&&r<=R) 63 { 64 if(maxx[rt]-minn[rt]==(LL)sqrt(maxx[rt])-(LL)sqrt(minn[rt])||maxx[rt]==minn[rt]) 65 { 66 LL z=(LL)sqrt(maxx[rt])-maxx[rt]; 67 sum[rt]+=z*(r-l+1); 68 maxx[rt]+=z,minn[rt]+=z,lazy[rt]+=z; 69 return; 70 } 71 } 72 int mid=(l+r)>>1; 73 pushdown(l,r,rt); 74 if(L<=mid)Sqrt(L,R,l,mid,rt<<1); 75 if(R>mid)Sqrt(L,R,mid+1,r,rt<<1|1); 76 pushup(rt); 77 } 78 LL query(int L,int R,int l,int r,int rt) 79 { 80 if(L<=l&&r<=R) 81 return sum[rt]; 82 int mid=(l+r)>>1; 83 LL ans=0; 84 pushdown(l,r,rt); 85 if(L<=mid)ans+=query(L,R,l,mid,rt<<1); 86 if(R>mid)ans+=query(L,R,mid+1,r,rt<<1|1); 87 pushup(rt); 88 return ans; 89 } 90 int main() 91 { 92 int t,n,m; 93 scanf("%d",&t); 94 while(t--) 95 { 96 scanf("%d%d",&n,&m); 97 build(1,n,1); 98 for(int i=0;i<m;i++) 99 { 100 int op,l,r; 101 LL x; 102 scanf("%d%d%d",&op,&l,&r); 103 if(op==1) 104 { 105 scanf("%lld",&x); 106 update(l,r,x,1,n,1); 107 } 108 else if(op==2) 109 { 110 Sqrt(l,r,1,n,1); 111 } 112 else if(op==3) 113 { 114 printf("%lld ",query(l,r,1,n,1)); 115 } 116 } 117 } 118 return 0; 119 } 120 /* 121 1 122 5 10 123 1 2 3 4 5 124 1 1 3 10 125 2 1 3 126 2 1 3 127 2 1 3 128 2 1 3 129 3 1 3 130 */