回家2天多,都在搞线段树了,第一是回家效率也不是很高,第二是线段树也不是很容易搞,前面说了poj2777的一道线段树,那题需要lazy,现在觉得,要是不用lazy的线段树好像不是很正规似的。这里突然想到一点,其实有些做法是无法用lazy实现的,像前面那题着色,单单只是覆盖,比如说你在一个区间多次覆盖了不同的颜色,但是你需要查询该区间的左右儿子时,你传递过去的只是最新的那个颜色,这样是比较容易实现的,再说说poj3468这题,试着考虑刚才类似的问题,假如我多次向某个区间做了add操作,那么那个区间节点该保存什么呢,当然是所有加的数的和,所以这里add是需要累加的,其实对它的儿子节点来说,就是加a,加b,等价于一次性把a+b都加上了。但是我想肯定有些操作是无法lazy的,但是我好像没想出来。
poj3468代码如下
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; struct node { int l,r; long long add,sum; }tr[500001]; int a[100001]; void cre(int l,int r,int node) { tr[node].l=l; tr[node].r=r; tr[node].add=0; tr[node].sum=0; if(l==r) return ; int mid=(l+r)/2; cre(l,mid,node*2); cre(mid+1,r,node*2+1); return ; } long long getsum(int l,int r,int node) { if(l==tr[node].l&&tr[node].r==r) return tr[node].sum; if(tr[node].add!=0) { tr[2*node].add+=tr[node].add; tr[2*node+1].add+=tr[node].add; tr[2*node].sum+=tr[node].add*(tr[2*node].r-tr[2*node].l+1); tr[2*node+1].sum+=tr[node].add*(tr[2*node+1].r-tr[2*node+1].l+1); tr[node].add=0; } int mid=(tr[node].l+tr[node].r)/2; long long c,c1,c2; if(l>mid) c=getsum(l,r,2*node+1); else if(r<=mid) c=getsum(l,r,2*node); else { c1=getsum(l,mid,2*node); c2=getsum(mid+1,r,2*node+1); c=c1+c2; } return c; } long long upd(int l,int r,int ad,int node) { if(l==tr[node].l&&tr[node].r==r) { tr[node].add+=ad; tr[node].sum+=ad*(r-l+1); return tr[node].sum; } if(tr[node].add!=0) { tr[2*node].add+=tr[node].add; tr[2*node+1].add+=tr[node].add; tr[2*node].sum+=tr[node].add*(tr[2*node].r-tr[2*node].l+1); tr[2*node+1].sum+=tr[node].add*(tr[2*node+1].r-tr[2*node+1].l+1); tr[node].add=0; } int mid=(tr[node].l+tr[node].r)/2; long long c1,c2; if(mid>=r) { c1=upd(l,r,ad,2*node); c2=getsum(mid+1,tr[node].r,2*node+1); } else if(mid<l) { c1=getsum(tr[node].l,mid,2*node); c2=upd(l,r,ad,2*node+1); } else { c1=upd(l,mid,ad,2*node); c2=upd(mid+1,r,ad,2*node+1); } tr[node].sum=c1+c2; return tr[node].sum; } int n,o; int main() { while(~scanf("%d%d",&n,&o)) { int i; cre(1,n,1); for(i=1;i<=n;i++) { scanf("%d",a+i); upd(i,i,a[i],1); } while(o--) { int a,b,c; char op[2]; scanf("%s",op); if(op[0]=='C') { scanf("%d%d%d",&a,&b,&c); upd(a,b,c,1); } else if(op[0]=='Q') { scanf("%d%d",&a,&b); printf("%lld\n",getsum(a,b,1)); } } } return 0; }