whu 1464 Deal whth Numbers 线段树维护区间除法

题意

  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,╮(╯▽╰)╭~~~

  

View Code
 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 }

 

posted @ 2013-04-15 09:35  yefeng1627  阅读(1233)  评论(0编辑  收藏  举报

Launch CodeCogs Equation Editor