POJ 3468 线段树裸题

  这些天一直在看线段树,因为临近期末,所以看得断断续续,弄得有些知识点没能理解得很透切,但我也知道不能钻牛角尖,所以配合着刷题来加深理解。

  然后,这是线段树裸题,而且是最简单的区间增加与查询,我参考了ACdreamer的模板,在此基础上自己用宏定义来精简了一下代码:

 1 #include<cstdio>
 2 typedef long long LL;
 3 #define root  int rt, int l, int r
 4 #define lson  rt*2, l, mid
 5 #define rson  rt*2+1, mid+1, r
 6 #define makemid  int mid= (l+r)>>1
 7 int a,b;
 8 LL c;
 9 
10 struct tree {
11     LL add,sum;
12 } s[400003];
13 
14 void build(root) {
15     s[rt].add= 0;
16     if(l==r){
17         scanf("%lld",&s[rt].sum);
18         return ;
19     }
20     makemid ;
21     build(lson);
22     build(rson);
23     s[rt].sum= s[rt*2].sum+s[rt*2+1].sum;
24 }
25 
26 inline void pushdown(int rt, int len) {
27     int ls= rt*2, rs= ls+1;
28     const LL &c= s[rt].add;
29     s[ls].add += c;
30     s[rs].add += c;
31     s[ls].sum += c*(len-len/2);
32     s[rs].sum += c*(len/2);
33     s[rt].add= 0;
34 }
35 
36 void update(root) {
37     if(a<=l && r<=b){
38         s[rt].add+= c;
39         s[rt].sum+= c*(r-l+1);
40         return ;
41     }
42     if(s[rt].add)    pushdown(rt,r-l+1);
43     makemid ;
44     if(a<=mid)    update(lson);
45     if(b>mid)    update(rson);
46     s[rt].sum= s[rt*2].sum+s[rt*2+1].sum;
47 }
48 
49 LL query(root) {
50     if(a<=l && r<=b)    return s[rt].sum;
51     if(s[rt].add)    pushdown(rt,r-l+1);
52     makemid ;
53     LL res= 0;
54     if(a<=mid)    res+= query(lson);
55     if(b>mid)    res+= query(rson);
56     return res;
57 }
58 
59 int main(){
60     int n,q;
61     while(~scanf("%d%d",&n,&q)){
62         build(1,1,n);
63         while(q--){
64             getchar();
65             if(getchar()=='Q'){
66                 scanf("%d%d",&a,&b);
67                 printf("%lld
",query(1,1,n));
68             }
69             else {
70                 scanf("%d%d%lld",&a,&b,&c);
71                 update(1,1,n);
72             }
73         }
74     }
75     return 0;
76 }

  原样的代码是:

 1 #include<cstdio>
 2 typedef long long LL;
 3 LL c;
 4 int a,b;
 5 
 6 struct tree{
 7     LL add,sum;
 8 } s[400003];
 9 
10 void build(int rt, int l, int r){
11     s[rt].add= 0;
12     if(l==r){
13         scanf("%lld",&s[rt].sum);
14         return ;
15     }
16     int mid= (l+r)>>1;
17     build(rt*2,l,mid);
18     build(rt*2+1,mid+1,r);
19     s[rt].sum= s[rt*2].sum+s[rt*2+1].sum;
20 }
21 
22 inline void pushdown(int rt, int len){
23     if(s[rt].add){
24         int ls= rt*2, rs= ls+1;
25         s[ls].add += s[rt].add;
26         s[rs].add += s[rt].add;
27         s[ls].sum += s[rt].add*(len-len/2);
28         s[rs].sum += s[rt].add*(len/2);
29         s[rt].add= 0;
30     }
31 }
32 
33 void update(int rt, int l, int r){
34     if(a<=l && r<=b){
35         s[rt].add+= c;
36         s[rt].sum+= c*(r-l+1);
37         return ;
38     }
39     pushdown(rt,r-l+1);
40     int mid= (l+r)>>1;
41     if(a<=mid)    update(rt*2,l,mid);
42     if(b>mid)    update(rt*2+1,mid+1,r);
43     s[rt].sum= s[rt*2].sum+s[rt*2+1].sum;
44 }
45 
46 LL query(int rt, int l, int r){
47     if(a<=l && r<=b)    return s[rt].sum;
48     pushdown(rt,r-l+1);
49     int mid= (l+r)>>1;
50     LL res= 0;
51     if(a<=mid)    res+= query(rt*2,l,mid);
52     if(b>mid)    res+= query(rt*2+1,mid+1,r);
53     return res;
54 }
55 
56 int main(){
57     int n,q;
58     while(~scanf("%d%d",&n,&q)){
59         build(1,1,n);
60         while(q--){
61             getchar();
62             if(getchar()=='Q'){
63                 scanf("%d%d",&a,&b);
64                 printf("%lld
",query(1,1,n));
65             }
66             else {
67                 scanf("%d%d%lld",&a,&b,&c);
68                 update(1,1,n);
69             }
70         }
71     }
72     return 0;
73 }
View Code

  线段树,不断进取中~~

原文地址:https://www.cnblogs.com/Newdawn/p/4197240.html