whu 1464 deal with numbers

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 }

 

你可能感兴趣的:(number)