题意
N个数,M个操作,操作有三类:
1. D,A,B,C 区间[a,b]中 大于0 的数 除以C,计算机整除
2. M,A,B,C 区间[a,b]所有数减去C
3. S,A,B 区间[a,b]求和
解法
区间更新和求和,线段树上延迟更新就可以了。主要是除法如何维护。
这里的数C <= 5*1E5 , 因为大于0才除,所以每个数最多被除 log(Ai) 次, N个数则最多被除 N*log(Ai) 次了。
所以做除法可以直接更新到底,还有就是使用一个标记,区间中都不可被除时,就没必要更新到底了。
另外,除数是1的时候,不能除,貌似后台数据好多1,╮(╯▽╰)╭~~~
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstdlib> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long LL; 8 9 const int N = 5e5+10; 10 //segment_Tree 11 #define lch rt<<1,l,m 12 #define rch rt<<1|1,m+1,r 13 LL sum[N<<2], add[N<<2]; 14 bool flag[N<<2]; 15 16 void push_up(int rt){ 17 sum[rt] = sum[rt<<1]+sum[rt<<1|1]; 18 flag[rt] = flag[rt<<1] | flag[rt<<1|1]; 19 } 20 void push_down(int rt,int L){ 21 if( add[rt] ){ 22 add[rt<<1] += add[rt]; 23 add[rt<<1|1] += add[rt]; 24 sum[rt<<1] += (L-(L>>1))*add[rt]; 25 sum[rt<<1|1] += (L>>1)*add[rt]; 26 add[rt] = 0; 27 } 28 } 29 void build(int rt,int l,int r){ 30 sum[rt] = add[rt] = 0; 31 if(l == r){ scanf("%lld",&sum[rt]); flag[rt] = (sum[rt]>0); return; } 32 int m = (l+r)>>1; 33 build(lch), build(rch); 34 push_up(rt); 35 } 36 void Minus(int rt,int l,int r,int a,int b,int c){ 37 if(a <= l && r <= b){ 38 add[rt] += c; sum[rt] += (r-l+1)*c; return; 39 } 40 push_down(rt,r-l+1); 41 int m = (l+r)>>1; 42 if( a <= m ) Minus( lch,a,b,c ); 43 if( m < b ) Minus( rch,a,b,c ); 44 push_up(rt); 45 } 46 void Division(int rt,int l,int r,int a,int b,int c){ 47 if( flag[rt] == 0 ) return; 48 if(l == r){ 49 if(sum[rt]>0) sum[rt] /= (LL)c; 50 flag[rt] = (sum[rt] > 0); return; 51 } 52 push_down(rt, r-l+1); 53 int m = (l+r)>>1; 54 if( a <= m ) Division( lch,a,b,c ); 55 if( m < b ) Division( rch,a,b,c ); 56 push_up(rt); 57 } 58 LL Sum(int rt,int l,int r,int a,int b){ 59 if(a <= l && r <= b) return sum[rt]; 60 push_down(rt,r-l+1); 61 int m = (l+r)>>1; 62 LL res = 0; 63 if( a <= m ) res += Sum(lch,a,b); 64 if( m < b ) res += Sum(rch,a,b); 65 return res; 66 } 67 68 int main(){ 69 // freopen("D.in","r", stdin); 70 // freopen("test.out","w",stdout); 71 int T; 72 scanf("%d", &T); 73 for(int Case = 1; Case <= T; Case++){ 74 int n, m, a, b, c; 75 char op[10]; 76 scanf("%d%d", &n,&m); 77 printf("Case %d:\n",Case); 78 build( 1, 1, n ); 79 for(int i = 0; i < m; i++){ 80 scanf("%s", op); 81 if( op[0] == 'D' ){ 82 scanf("%d%d%d",&a,&b,&c); 83 if( c == 1 ) continue; 84 Division(1,1,n,a,b,c); 85 } 86 else if( op[0] == 'M' ){ 87 scanf("%d%d%d",&a,&b,&c); 88 Minus(1,1,n,a,b,-c); 89 } 90 else{ 91 scanf("%d%d",&a,&b); 92 LL res = Sum(1,1,n,a,b); 93 printf("%lld\n",res); 94 } 95 } 96 puts(""); 97 } 98 return 0; 99 }