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 }

 

posted @ 2013-08-25 10:40  Teilwall  阅读(303)  评论(0编辑  收藏  举报