hdu4107(线段数的懒惰标记)

http://acm.hdu.edu.cn/showproblem.php?pid=4107

思路:在结构体中开max、min域,max、min用来标记某一段区间的最大最小值。在更新数据的时候,用区间的max\min去与p比较,如果整段区间都小于p,那么num+=c;如果min>=p,那么num+=2*c;这样,就不用每次都更新到最低端...........

#include<iostream>
using namespace std;
#define M 200005
struct
{
	int l,r,num;
	int max,min;
}tree[M*4];
int n,m,p;
void creat(int i,int l,int r)
{
	int mid=(l+r)/2;
	tree[i].l=l;
	tree[i].r=r;
	tree[i].num=0;
	tree[i].max=0;
	tree[i].min=0;
	if(l==r)
		return;
	creat(i*2,l,mid);
	creat(i*2+1,mid+1,r);
}
void updata(int i,int l,int r,int v)
{
	int mid=(tree[i].l+tree[i].r)/2;
	if(tree[i].l==l&&tree[i].r==r)
	{
		if(tree[i].min>=p)
		{
			tree[i].num+=2*v;
			tree[i].max+=2*v;
			tree[i].min+=2*v;
			return ;
		}
		if(tree[i].max<p)
		{
			tree[i].num+=v;
			tree[i].max+=v;
			tree[i].min+=v;
			return ;
		}
	}
	if(tree[i].num!=0)            //如果区间值不为0,则把区间值往下传递,因为num记录的是整段区间所要加的值
	{
		tree[i*2].num+=tree[i].num;
		tree[i*2].max+=tree[i].num;
		tree[i*2].min+=tree[i].num;
		tree[i*2+1].num+=tree[i].num;
		tree[i*2+1].min+=tree[i].num;
		tree[i*2+1].max+=tree[i].num;
		tree[i].num=0;                            //加完后,要将num清零,以免重复加..........
	}
	if(r<=mid)
		updata(i*2,l,r,v);
	else if(l>mid)
		updata(i*2+1,l,r,v);
	else
	{
		updata(i*2,l,mid,v);
		updata(i*2+1,mid+1,r,v);
	}
	tree[i].max=tree[i*2].max>tree[i*2+1].max ? tree[i*2].max:tree[i*2+1].max;        //更新区间的最大最小值,方便下一次判断
	tree[i].min=tree[i*2].min<tree[i*2+1].min ? tree[i*2].min:tree[i*2+1].min;
}
void quest(int i)
{
	if(tree[i].l==tree[i].r)
	{
		if(tree[i].l!=1)
			printf(" ");
		printf("%d",tree[i].num);
		return;
	}
	if(tree[i].num!=0)
	{
		tree[i*2].num+=tree[i].num;
		tree[i*2+1].num+=tree[i].num;
		tree[i].num=0;
	}
	quest(i*2);
	quest(i*2+1);
}
int main()
{
	while(scanf("%d%d%d",&n,&m,&p)>0)
	{
		creat(1,1,n);
		while(m--)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			updata(1,a,b,c);
		}
		quest(1);
		printf("\n");
	}
	return 0;
}
 

 

posted @ 2012-12-25 14:29  紫忆  阅读(521)  评论(0编辑  收藏  举报