题目链接:
http://poj.org/problem?id=3468
题目意思:
有一个整数序列,有两种操作,C a b c 把区间【a,b】内所有数都加上c,Q a b 查询区间【a,b】内所有数的和。
解题思路:
简单区间更新,坑了很久。发现了以前的一些错误。
对每个区间一个va表示是否已经下传了,下传时要更新左右儿子,不能表示当前区间是否已经更新,否则会出错。比如:
10 111
1 2 3 4 5 6 7 8 9 10
C 1 10 3
C 6 10 3
Q 1 10
如果按照错误写法,第一个操作,更新了1-10,并且下传了,注意左右儿子此时并没更新,操作二更新了6-10,下传了。上传时把6-10更新的上传了,但左儿子并没有更新。
正确写法:保存是否下传,这样就保证了当前已经更新了,当不经过该分支时,上传不会使没有更新的节点传上去。
代码:
//#include<CSpreadSheet.h> #include<iostream> #include<cmath> #include<cstdio> #include<sstream> #include<cstdlib> #include<string> #include<string.h> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #include<ctime> #include<bitset> #define eps 1e-6 #define INF 0x3f3f3f3f #define PI acos(-1.0) #define ll __int64 //#define ll long long #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 #define M 1000000007 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define Maxn 110000 struct Node { ll sum; ll va; //0表示已经下传,非零表示没有下传,先更新自己后更新下传量 }node[Maxn<<2]; void pushup(int rt) { node[rt].sum=node[rt<<1].sum+node[(rt<<1)|1].sum; } void build(int l,int r,int rt) { node[rt].sum=0; if(l==r) { scanf("%I64d",&node[rt].sum); return ; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } void pushdown(int rt,int num) { node[rt<<1].va+=node[rt].va; node[rt<<1].sum+=node[rt].va*((num+1)/2); //下传 node[rt<<1|1].va+=node[rt].va; node[rt<<1|1].sum+=node[rt].va*(num/2); } void add(int L,int R,int l,int r,int rt,ll va) { if(L<=l&&R>=r) { node[rt].va+=va; node[rt].sum+=va*(r-l+1); //先更新后下传 if(l!=r) pushdown(rt,r-l+1); node[rt].va=0;//已经下传喽 return ; } if(node[rt].va) //没有下传 往下下传 { if(l!=r) pushdown(rt,r-l+1); node[rt].va=0; } int m=(l+r)>>1; if(L<=m) add(L,R,lson,va); if(R>m) add(L,R,rson,va); pushup(rt); } ll query(int L,int R,int l,int r,int rt) { //printf(":%d %I64d\n",rt,node[rt].sum); if(L<=l&&R>=r) { if(l!=r) //下传 pushdown(rt,r-l+1); node[rt].va=0; return node[rt].sum; } if(node[rt].va) { if(l!=r) pushdown(rt,r-l+1); node[rt].va=0; } int m=(l+r)>>1; ll ans=0; if(L<=m) ans+=query(L,R,lson); if(R>m) ans+=query(L,R,rson); pushup(rt); return ans; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n,q; while(~scanf("%d%d",&n,&q)) { build(1,n,1); for(int i=1;i<=q;i++) { char temp[3]; scanf("%s",temp); int a,b; ll c; if(*temp=='Q') { scanf("%d%d",&a,&b); printf("%I64d\n",query(a,b,1,n,1)); } else { scanf("%d%d%I64d",&a,&b,&c); add(a,b,1,n,1,c); } } } return 0; } /* 5 100 1 2 3 4 5 C 2 3 2 C 2 2 2 Q 1 5 */ /* 10 22 1 2 3 4 5 6 7 8 9 10 C 1 10 3 C 6 10 3 C 6 9 3 Q 6 10 C 8 9 -100 C 7 9 3 C 7 10 3 C 1 10 3 Q 6 10 Q 6 9 Q 8 9 Q 7 9 Q 7 10 Q 1 10 Q 2 4 C 3 6 3 Q 9 9 Q 1 1 Q 5 5 Q 6 6 Q 7 7 Q 6 8 */