回家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;
}