hdu1698(线段树懒惰法)

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

大意:给一组棍子染色,不同的颜色有不同的值,执行一系列的区间染色后,问这组棍子的总值是多少。

题目分析:建树:节点的域有左右节点和颜色,l,r,num;num=0时表示这个区间由多种颜色覆盖。

更新的时候,如果更新区间比当前区间小,并且当前区间的颜色大于0,说明已经被完全染色,就把该区间颜色传递到左右子树上,该区间染色为0,然后根据更新区间的大小,在左右子树上去搜索。

求和的时候遇到区间的num>0的时候说明完全被染色过了,就把区间的长度乘以颜色的值加到总和里面去,然后结束这个方向的递归查询,

代码:

#include<iostream>

using namespace std;

struct node

{

	int l,r,num;

}tree[400000];

int ans;

void build(int i,int l,int r)

{

	tree[i].l=l;

	tree[i].r=r;

	tree[i].num=1;

	if(l==r)

		return;

	else

	{

		int mid=(l+r)/2;

		build(i*2,l,mid);

		build(i*2+1,mid+1,r);

	}

}

void updata(int i,int l,int r,int v)

{

	if(l==tree[i].l&&r==tree[i].r)

	{

		tree[i].num=v;

		return;

	}

	if(tree[i].num==v)

		return ;

	if(tree[i].num>0)                 

	{

		tree[i*2+1].num=tree[i*2].num=tree[i].num;

		tree[i].num=0;

	}

	int mid=(tree[i].l+tree[i].r)/2;

	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);

		}

}

void getsum(int i,int l,int r)

{

	if(tree[i].num>0)

	{

		ans+=(tree[i].r-tree[i].l+1)*tree[i].num;    //注意,要加1

		return ;

	}

	else

	{

		int mid=(tree[i].l+tree[i].r)/2;

		if(r<=mid)

			getsum(i*2,l,r);

		else

			if(l>mid)

				getsum(i*2+1,l,r);

			else

			{

				getsum(i*2,l,mid);

				getsum(i*2+1,mid+1,r);

			}

	}



}

int main()

{

	int t,k=0;;

	scanf("%d",&t);

	while(t--)

	{

		int n;

		scanf("%d",&n);

		int m;

		scanf("%d",&m);

		build(1,1,n);

		while(m--)

		{

			int x,y,z;

			scanf("%d%d%d",&x,&y,&z);

			updata(1,x,y,z);

		}

		ans=0;

		getsum(1,1,n);

		printf("Case %d: The total value of the hook is %d.\n",++k,ans); 

	}

	return 0;

}

 

你可能感兴趣的:(HDU)