您的位置:首页 > 其它

线段树专辑—— pku 3468 A Simple Problem with Integers

2011-11-09 21:28 399 查看
http://poj.org/problem?id=3468

典型的一道基于lazy传递的线段树题目,这题和一般题目不同的地方在于,它的每次操作不是简单的覆盖线段,而是累加。记得第一次写的时候纠结了好久。

好的,既然是累加,那么如何传递lazy呢?答案是传递累加值!

为线段树加一个add域,表示该线段需要加几。如果某区间的add不为0,那么就将该区间的add传递给其子区间,并且跟新子区间的sum_val值。

解这题最关键的就是要能够分清楚啥东西要传递,传递下去将有什么影响,其他的都好说!整体来说还是蛮轻松的

View Code

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

struct node
{
int l;
int r;
__int64 add;
__int64 sum_val;
};

node tree[500000];
int n,m;
__int64 num[100001];

void build(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
tree[i].add=0;
if(l==r)
{
tree[i].sum_val=num[l];
return;
}
int mid=(l+r)/2;
build(2*i,l,mid);
build(2*i+1,mid+1,r);
tree[i].sum_val=tree[2*i].sum_val+tree[2*i+1].sum_val;
}

void updata(int i,int l,int r,__int64 w)
{
if(tree[i].l>r || tree[i].r<l)
return;
if(tree[i].l>=l && tree[i].r<=r)
{
tree[i].add+=w;  //注意是+=,因为这不是简单的覆盖
tree[i].sum_val+=(tree[i].r-tree[i].l+1)*w; //由于区间所有的值都需要加上w,那么自然整段区间就是加上(w*区间大小)了
return;
}
if(tree[i].add!=0)
{
tree[2*i].add+=tree[i].add; //同上,注意是+=
tree[2*i+1].add+=tree[i].add;
tree[2*i].sum_val+=(tree[2*i].r-tree[2*i].l+1)*tree[i].add;
tree[2*i+1].sum_val+=(tree[2*i+1].r-tree[2*i+1].l+1)*tree[i].add;
tree[i].add=0;
}
updata(2*i,l,r,w);
updata(2*i+1,l,r,w);
tree[i].sum_val=tree[2*i].sum_val+tree[2*i+1].sum_val; //回溯跟新
}

__int64 ans;
void find(int i,int l,int r)
{
if(tree[i].l>r || tree[i].r<l)
return;
if(tree[i].l>=l && tree[i].r<=r)
{
ans+=tree[i].sum_val;
return;
}
if(tree[i].add!=0)
{
tree[2*i].add+=tree[i].add;
tree[2*i+1].add+=tree[i].add;
tree[2*i].sum_val+=(tree[2*i].r-tree[2*i].l+1)*tree[i].add;
tree[2*i+1].sum_val+=(tree[2*i+1].r-tree[2*i+1].l+1)*tree[i].add;
tree[i].add=0;
}
find(2*i,l,r);
find(2*i+1,l,r);
}

int main()
{
int i,a,b;
__int64 w;
char c;
freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&m)==2)
{
for(i=1;i<=n;i++)
{
scanf("%I64d",&num[i]);
}
build(1,1,n);
for(i=0;i<m;i++)
{
getchar();
scanf("%c",&c);
if(c=='Q')
{
scanf("%d%d",&a,&b);
ans=0;
find(1,a,b);
printf("%I64d\n",ans);
}
else
{
scanf("%d%d%I64d",&a,&b,&w);
updata(1,a,b,w);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: