码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3468 A Simple Problem with Integers 线段树

时间:2015-03-20 01:13:14      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:

  这道题属于线段树的区间修改

给出一个序列,对其进行Q次操作,

"C c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q b" means querying the sum of AaAa+1, ... , Ab.

注意,这道题我wa了4次,在那里查了3个小时,wa原因,一个应该是long long 型的被我写成了int  ,悲剧的开始。

    讲讲我对线段树区间修改的理解吧。

    需要有个操作,建树,更新,维护,查询。

  1.建树:首先就是把数据建起来嘛,是一个dfs的过程,对于一个节点,若该节点的区间只有一个,则为叶子节点,对该叶子进行赋值,否则建其左子树,和右子树,

然后在递归结束前进行维护,更新该节点本身的信息。

  2.更新:更新的时候不断递归,直到递归边界 (L<=l&&R>=r),对于每一个递归,在递归结束之前需要重新计算本节点的附加信息。

  3.维护:维护就是维护一个节点的信息,2中说要在递归 结束之前重新计算本节点的附加信息,怎么计算,就是用到维护这个操作了。

  4查询:查询的时候是不断递归,直到递归边界(L<=l&&R>=r) 时,用边界区间的附加信息更新答案。

  sum[i] : 维护 i 对应区间的数据的和。

     addv[i] : 表示 i 对应区间的每一个数据都需要加 addv[i] ,所以每一个边界区间的结果不能直接使用,还要考虑祖先节点对她的影响。

 

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #define lson l,m,rt<<1
 4 #define rson m+1,r,rt<<1|1
 5 const int maxn=100000+10;
 6 long long  sum[maxn<<2];
 7 long long  addv[maxn<<2];
 8 void maintain(int l,int r,int rt)
 9 {
10     sum[rt]=0;
11     if(r>l)
12         sum[rt]=sum[rt<<1]+sum[rt<<1|1];
13     sum[rt]+=addv[rt]*(r-l+1);
14 }
15 void build(int l,int r,int rt)
16 {
17     if(l==r){
18         scanf("%I64d",&addv[rt]);
19     }
20     else{
21         int m=(l+r)>>1;
22         build(lson);
23         build(rson);
24     }
25     maintain(l,r,rt);
26 }
27 void update(int L,int R,int  w,int l,int r,int rt)
28 {
29     if(L<=l&&R>=r){
30         addv[rt]+=w;
31     }
32     else{
33         int m=(l+r)>>1;
34         if(L<=m)
35             update(L,R,w,lson);
36         if(R>m)
37             update(L,R,w,rson);
38     }
39     maintain(l,r,rt);
40 }
41 long long  _sum;
42 void query(int L,int R,int l,int r,int rt,long long  add)
43 {
44     if(L<=l&&R>=r)
45         _sum+=sum[rt]+add*(r-l+1);
46     else{
47         int m=(l+r)>>1;
48         if(L<=m)
49             query(L,R,lson,add+addv[rt]);
50         if(R>m)
51             query(L,R,rson,add+addv[rt]);
52     }
53 }
54 int main()
55 {
56     int n,q;
57     while(scanf("%d%d",&n,&q)!=EOF)
58     {
59         memset(addv,0,sizeof(addv));
60         build(1,n,1);
61         char s[3];
62         int u,v,w;
63         for(int i=1;i<=q;i++){
64             scanf("%s",&s);
65             if(s[0]==C){
66                 scanf("%d%d%d",&u,&v,&w);
67                 update(u,v,w,1,n,1);
68             }
69             else{
70                 scanf("%d%d",&u,&v);
71                 _sum=0;
72                 query(u,v,1,n,1,0);
73                 printf("%I64d\n",_sum);
74             }
75         }
76     }
77     return 0;
78 }
View Code

 

poj 3468 A Simple Problem with Integers 线段树

标签:

原文地址:http://www.cnblogs.com/-maybe/p/4352214.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!