POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目链接

这个真费劲。。。其实我也不懂 为什么。。。大体思想是,如果把区间更新了,开始的时候只把用懒惰标记标记那个区间,而不更新底层元素,而如果查询的时候顺带着把lz标记给消除。。。多敲几遍,多调试一下,看看中间过程,就应该理解了。

 1 #include <stdio.h>

 2 #include <string.h>

 3 #include <stdlib.h>

 4 #define N 100001

 5 #define ll __int64

 6 ll p[4*N],lz[4*N];

 7 void pushup(int rt)

 8 {

 9     p[rt] = p[rt<<1]+p[rt<<1|1];

10 }

11 void pushdown(int rt,int m)//消除懒惰标记,m记录区间长度

12 {

13     if(lz[rt])

14     {

15         lz[rt<<1] += lz[rt];//把他传递给儿子们

16         lz[rt<<1|1] += lz[rt];

17         p[rt<<1] += lz[rt]*(m - (m>>1));//更新线段树上的元素,注意位运算优先级的比较低啊!!

18         p[rt<<1|1] += lz[rt]*(m>>1);

19         lz[rt] = 0;//消除标记

20     }

21 }

22 void build(int l,int r,int rt)//建树

23 {

24     int m;

25     lz[rt] = 0;

26     if(l == r)

27     {

28         scanf("%I64d%*c",&p[rt]);

29         return ;

30     }

31     m = (l+r)>>1;

32     build(l,m,rt<<1);

33     build(m+1,r,rt<<1|1);

34     pushup(rt);

35 }

36 ll query(int L,int R,int l,int r,int rt)//L,R表示最后查询的区间。l,r表示中间过程历遍的区间。

37 {

38     int m;

39     ll sum = 0;

40     if(l >= L&&r <= R)

41     {

42         return p[rt];//如果l-r在L-R之间的话,直接返回

43     }

44     pushdown(rt,r - l + 1);//消除懒惰标记

45     m = (l + r) >> 1;

46     if(L <= m)//查找

47         sum += query(L,R,l,m,rt<<1);

48     if(R > m)

49         sum += query(L,R,m+1,r,rt<<1|1);

50     return sum;

51 }

52 void update(int L,int R,int l,int r,int rt,int sc)

53 {

54     int m;

55     if(l >= L&&r <= R)

56     {

57         lz[rt] += sc;//标记懒惰

58         p[rt] += sc*(r - l + 1);

59         return ;

60     }

61     pushdown(rt,r-l+1);

62     m = (l + r) >> 1;

63     if(L <= m) update(L,R,l,m,rt<<1,sc);

64     if(R > m) update(L,R,m+1,r,rt<<1|1,sc);

65     pushup(rt);

66 }

67 int main()

68 {

69     int n,m,i,x,y,z;

70     char str[10];

71     scanf("%d%d",&n,&m);

72     build(1,n,1);

73     for(i = 1; i <= m; i ++)

74     {

75         scanf("%s%d%d%*c",str,&x,&y);

76         if(str[0] == 'Q')

77         {

78             printf("%I64d\n",query(x,y,1,n,1));

79         }

80         else if(str[0] == 'C')

81         {

82             scanf("%d%*c",&z);

83             update(x,y,1,n,1,z);

84         }

85     }

86     return 0;

87 }

你可能感兴趣的:(Integer)