题目链接:http://poj.org/problem?id=3468
思路:线段树+lazy思想
当要增加的区间覆盖当前区间,则直接打上标记返回,当下次查询这个区间儿子区间的时候,直接标记往下传。
可以想象,这个标记表示的是这个区间表示的整个区间的标记,是整个子树的性质,当你不需要用到这个区间的儿子区
间的时候,你可以不把操作
都做到底,而是要用到的时候再往下传
#include<stdio.h>
#define N 100010
#define L(a) (a)<<1
#define R(a) (a)<<1|1
struct node
{
int l,r;
__int64 tnc,sum;
}line[N<<2];
int num[N];
void create(int k,int x,int y)
{
line[k].l=x;
line[k].r=y;
line[k].tnc=0;
if(x==y)
{
line[k].sum=num[x];
return;
}
int mid=(x+y)>>1;
create(L(k),x,mid);
create(R(k),mid+1,y);
line[k].sum=line[L(k)].sum+line[R(k)].sum;
}
void get(int k)
{
line[L(k)].sum+=(line[L(k)].r-line[L(k)].l+1)*line[k].tnc;
line[R(k)].sum+=(line[R(k)].r-line[R(k)].l+1)*line[k].tnc;
line[L(k)].tnc+=line[k].tnc;
line[R(k)].tnc+=line[k].tnc;
line[k].tnc=0;
}
void updata(int k,int x,int y,__int64 val)
{
if(x<=line[k].l&&line[k].r<=y)
{
line[k].tnc+=val;
line[k].sum+=(line[k].r-line[k].l+1)*val;
return;
}
if(line[k].tnc) get(k);
int mid=(line[k].l+line[k].r)>>1;
if(y<=mid)
updata(L(k),x,y,val);
else if(x>mid)
updata(R(k),x,y,val);
else
{
updata(L(k),x,mid,val);
updata(R(k),mid+1,y,val);
}
line[k].sum=line[L(k)].sum+line[R(k)].sum;
}
__int64 visit(int k,int x,int y)
{
if(x<=line[k].l&&line[k].r<=y)
{
return line[k].sum;
}
if(line[k].tnc) get(k);
int mid=(line[k].r+line[k].l)>>1;
if(y<=mid)
return visit(L(k),x,y);
else if(x>mid)
return visit(R(k),x,y);
else
{
return visit(L(k),x,mid)+visit(R(k),mid+1,y);
}
}
int main()
{
int n,q,i,a,b,c;
char ch[7];
while(scanf("%d%d",&n,&q)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
create(1,1,n);
for(i=1;i<=q;i++)
{
scanf("%s",ch);
if(ch[0]=='C')
{
scanf("%d%d%d",&a,&b,&c);
updata(1,a,b,c);
}
else
{
scanf("%d%d",&a,&b);
__int64 ans=visit(1,a,b);
printf("%I64d\n",ans);
}
}
}
return 0;
}