WHU 1464 deal with numbershtml
題意:ui
給你一串數字,對着串數字有三項操做:spa
Minus a,b,c:對區間[a,b]總的每一個數都減c。code
Division a,b,c:對區間[a,b]中的每一個數都除以c。htm
Sum a,b:求出區間[a,b]的和~blog
因爲該題是對區間裏的全部數進行操做,用通常的線段樹會TLE,在這裏要用到Lazy_Tag。而後另外要注意的是除法如何維護:這裏的數C <= 5*1E5 , 由於大於0才除,因此每一個數最多被除 log(Ai) 次, N個數則最多被除 N*log(Ai) 次了。因此作除法能夠直接更新到底,還有就是使用一個標記,區間中都不可被除時,就不必更新到底了。另外,除數是1的時候,不能除,貌似後臺數據好多1,~\(≧▽≦)/~get
代碼【來自:http://www.cnblogs.com/yefeng1627/archive/2013/04/15/3021460.html】:it
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 }