LA 4108 SKYLINE 线段树

LA 4108

题意:T组数据,每次输入n,接下来n次操作,每次输入 L R H,表示建筑物的左边界,右边界,和高度,要求计算这次输入的建筑物覆盖度,比如,原来1-3的最高高度是3,3-5的最高高度是4,5-6的最高高度是5,如果输入1 6 4,则这次覆盖度是5-1=4,并且更新这个区间的最高高度,求n次操作的总覆盖度。

比较容易的一个区间更新并且求区间的线段树,设max[ o ]为o这个节点所含区间中的最大高度,设set[ o ]为o这个区间是否覆盖,如果覆盖设为1,没覆盖为0,每次跟新一个区间的高度,都把这个区间的set[ o ]设为1,如果某个节点的set值为1,那么要更新其子节点时,把该节点set值和max值传递到其子节点,并把该节点的set值0。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=3e5+5;
const int inf=1e8;
int n,ql,qr,h,_max[maxn],_set[maxn],ans;
void init()
{
	ans=0;
	for(int i=0;i<maxn;i++)
	_max[i]=_set[i]=0;
}
void maintain(int o,int ls,int rs)
{
	int t=max(_max[ls],_max[rs]);
	_max[o]=max(_max[o],t);	
}
void pushdown(int o,int ls,int rs)
{
	if(_set[o])
	{
		_set[o]=0;
		_set[ls]=_set[rs]=1;
		_max[ls]=_max[rs]=_max[o];
	}
}
void update(int L,int R,int o)
{
	if(L>=ql&&R<=qr&&_max[o]<=h)
	{
		_set[o]=1;
		_max[o]=h;
		ans+=R-L+1;
		return;
	}
	if(_max[o]>h&&_set[o]==1)
	return;
	int ls=o*2,rs=o*2+1;
	int m=(L+R)/2;
	pushdown(o,ls,rs);
	if(ql<=m)	
	update(L,m,ls);
	if(qr>m)		
	update(m+1,R,rs);
	maintain(o,ls,rs);
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int i;
		scanf("%d",&n);
		init();
		while(n--)
		{
			scanf("%d%d%d",&ql,&qr,&h);
			qr--;
			update(1,100000,1);
		}
		printf("%d\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/ccsu_cat/article/details/80774607
LA
今日推荐