POJ 3468 :A Simple Problem with Integers——区间更新线段树经典题目

/*

经典区间成段更新题目。

题意:给出一个长度n的数字序列,已经m个操作,
Q操作给出l,r:访问区间[l,r]的数字和;
C操作给出l,r,x:将区间[l,r]内的所有数字都加上x。
Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4


Sample Output

4
55
9
15

*/

花了好些天研究ppt与别人的题解,不断的手动模拟才稍微理解lazy标记的熟络。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
#define LL __int64

struct node
{
	int l,r;
	LL lazy,sum;  //lazy为延迟标记
	int Len() { return r-l+1; }
	int Mid() { return (l+r)>>1; }
}tree[3*maxn];
int a[maxn];

void Lazy(int p)
{
	if(tree[p].lazy)
	{
		tree[p<<1].lazy+=tree[p].lazy;
		tree[p<<1|1].lazy+=tree[p].lazy;
		
		tree[p<<1].sum+=tree[p<<1].Len()*tree[p].lazy;
		tree[p<<1|1].sum+=tree[p<<1|1].Len()*tree[p].lazy;
		tree[p].lazy=0;
	}
}

void BuildTree(int p,int l,int r)
{
	tree[p].l=l,tree[p].r=r,tree[p].lazy=0;
	if(l==r)
	{
		tree[p].sum=a[l];
		return ;
	}
	int mid=(l+r)>>1;
	BuildTree(p<<1,l,mid);
	BuildTree(p<<1|1,mid+1,r);
	tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
}

void change(int p,int l,int r,int x)
{
	if(tree[p].l==l&&tree[p].r==r)
	{
		tree[p].lazy+=x;
		tree[p].sum+=x*tree[p].Len();
		return;
	}
	
	Lazy(p);  //标记下传
	int mid=tree[p].Mid();
	if(r<=mid)
		change(p<<1,l,r,x);
	else if(l>mid)
		change(p<<1|1,l,r,x);
	else
	{
		change(p<<1,l,mid,x);
		change(p<<1|1,mid+1,r,x);
	}
	tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
}

LL query(int p,int l,int r)
{
	if(tree[p].l==l&&tree[p].r==r)
		return tree[p].sum;
	Lazy(p);
	int mid=tree[p].Mid();
	if(r<=mid)
		return query(p<<1,l,r);
	else if(l>mid)
		return query(p<<1|1,l,r);
	else
		return query(p<<1,l,mid)+query(p<<1|1,mid+1,r);
}

int main()
{
	int n,Q,l,r,x,i;
	char orde[3];
	scanf("%d%d",&n,&Q);
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	BuildTree(1,1,n);
	while(Q--)
	{
		scanf("%s%d%d",orde,&l,&r);
		if(l>r)
			swap(l,r);
		if(orde[0]=='C')
		{
			scanf("%d",&x);
			change(1,l,r,x);
		}
		else
			printf("%I64d\n",query(1,l,r));
	}
	return 0;
}


你可能感兴趣的:(POJ 3468 :A Simple Problem with Integers——区间更新线段树经典题目)