whu 1464 deal with numbers
题意:
给你一串数字,对着串数字有三项操作:
Minus a,b,c:对区间[a,b]总的每个数都减c。
Division a,b,c:对区间[a,b]中的每个数都除以c。
Sum a,b:求出区间[a,b]的和~
由于该题是对区间里的所有数进行操作,用一般的线段树会TLE,在这里要用到Lazy_Tag。然后另外要注意的是除法如何维护:这里的数C <= 5*1E5 , 因为大于0才除,所以每个数最多被除 log(Ai) 次, N个数则最多被除 N*log(Ai) 次了。所以做除法可以直接更新到底,还有就是使用一个标记,区间中都不可被除时,就没必要更新到底了。另外,除数是1的时候,不能除,貌似后台数据好多1,~\(≧▽≦)/~
代码【来自:http://www.cnblogs.com/yefeng1627/archive/2013/04/15/3021460.html】:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstdlib> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long LL; 8 const int N = 5e5+10; 9 #define lch rt<<1,l,m 10 #define rch rt<<1|1,m+1,r 11 LL sum[N<<2], add[N<<2]; 12 bool flag[N<<2]; 13 14 void push_up(int rt){ 15 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 16 flag[rt]=flag[rt<<1] | flag[rt<<1|1]; 17 } 18 19 void push_down(int rt,int L){ 20 if( add[rt] ){ 21 add[rt<<1]+=add[rt]; 22 add[rt<<1|1]+=add[rt]; 23 sum[rt<<1]+=(L-(L>>1))*add[rt]; 24 sum[rt<<1|1]+=(L>>1)*add[rt]; 25 add[rt]=0; 26 } 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 37 void Minus(int rt,int l,int r,int a,int b,int c){ 38 if(a <= l && r <= b){ 39 add[rt] += c; sum[rt] += (r-l+1)*c; return; 40 } 41 push_down(rt,r-l+1); 42 int m = (l+r)>>1; 43 if( a <= m ) Minus( lch,a,b,c ); 44 if( m < b ) Minus( rch,a,b,c ); 45 push_up(rt); 46 } 47 48 void Division(int rt,int l,int r,int a,int b,int c){ 49 if( flag[rt] == 0 ) return; 50 if(l == r){ 51 if(sum[rt]>0) sum[rt] /= (LL)c; 52 flag[rt] = (sum[rt] > 0); return; 53 } 54 push_down(rt, r-l+1); 55 int m = (l+r)>>1; 56 if( a <= m ) Division( lch,a,b,c ); 57 if( m < b ) Division( rch,a,b,c ); 58 push_up(rt); 59 } 60 61 LL Sum(int rt,int l,int r,int a,int b){ 62 if(a<=l && r<=b) return sum[rt]; 63 push_down(rt,r-l+1); 64 int m=(l+r)>>1; 65 LL res=0; 66 if(a<=m) res+=Sum(lch,a,b); 67 if(m<b) res+=Sum(rch,a,b); 68 return res; 69 } 70 71 int main(){ 72 int T; 73 scanf("%d", &T); 74 for(int Case = 1; Case <= T; Case++){ 75 int n, m, a, b, c; 76 char op[10]; 77 scanf("%d%d", &n,&m); 78 printf("Case %d:\n",Case); 79 build( 1, 1, n ); 80 for(int i = 0; i < m; i++){ 81 scanf("%s", op); 82 if( op[0] == 'D' ){ 83 scanf("%d%d%d",&a,&b,&c); 84 if( c == 1 ) continue; 85 Division(1,1,n,a,b,c); 86 } 87 else if( op[0] == 'M' ){ 88 scanf("%d%d%d",&a,&b,&c); 89 Minus(1,1,n,a,b,-c); 90 } 91 else{ 92 scanf("%d%d",&a,&b); 93 LL res = Sum(1,1,n,a,b); 94 printf("%lld\n",res); 95 } 96 } 97 puts(""); 98 } 99 return 0; 100 }