您的位置:首页 > 其它

poj 3468 线段树+懒标记

2015-08-02 19:29 267 查看
简单的线段树区间求和问题,每次改变区间值得时候采用懒标记的操作,等到下次经过这个区间的时候再将懒标记向下传递。
#include <cstdio>
#include <iostream>

using namespace std;

int n,q;
int a[100005];
long long sum[500005],lazy[500005];

void build(int l,int r,int k)
{
lazy[k]==0;
if (l==r)
{
sum[k]=a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,2*k);
build(mid+1,r,2*k+1);
sum[k]=sum[2*k]+sum[2*k+1];
}

void pushdown(int m,int k)
{
if (lazy[k])
{
lazy[2*k]+=lazy[k];
lazy[2*k+1]+=lazy[k];
sum[2*k]+=(long long)lazy[k]*(m-(m>>1));
sum[2*k+1]+=(long long)lazy[k]*(m>>1);
lazy[k]=0;
}
}

long long work(int l,int r,int k,int L,int R)
{
if ((L<=l)&&(r<=R))
{
return sum[k];
}
pushdown(r-l+1,k);
int mid=(l+r)>>1;
if (R<=mid) return work(l,mid,2*k,L,R);
else if (L>mid) return work(mid+1,r,2*k+1,L,R);
else return work(l,mid,2*k,L,mid)+work(mid+1,r,2*k+1,mid+1,R);
}

void change(int l,int r,int k,int L,int R,int VAL)
{
if ((L<=l)&&(r<=R))
{
lazy[k]+=VAL;
sum[k]+=(long long)VAL*(R-L+1);
return;
}
pushdown(r-l+1,k);
int mid=(l+r)>>1;
if (R<=mid) change(l,mid,2*k,L,R,VAL);
else if(L>mid) change(mid+1,r,2*k+1,L,R,VAL);
else
{
change(l,mid,2*k,L,mid,VAL);
change(mid+1,r,2*k+1,mid+1,R,VAL);
}
sum[k]=sum[2*k]+sum[2*k+1];
}

int main()
{
scanf("%d%d",&n,&q);
for (int i=0;i<n;i++) scanf("%d",&a[i]);
build(0,n-1,1);
for (int i=0;i<q;i++)
{
char ch[5];
int a,b,c;
scanf("%s%d%d",ch,&a,&b);
a--; b--;
if (ch[0]=='Q')
{
printf("%I64d\n",work(0,n-1,1,a,b));
}
else
{
scanf("%d",&c);
change(0,n-1,1,a,b,c);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: