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 }

 

你可能感兴趣的:(number)