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 }
posted @ 2012-08-10 16:16  Naix_x  阅读(204)  评论(0编辑  收藏  举报