UVA 1232 - SKYLINE

闲得无聊刷白书

一开始想得很简单,维护一个区间最小值(修改时忽略下面的高度)和当前区间高度(区间每一点高度都同一才有效),然后就是区间修改,标记什么的。

结果发现下面的高度传不上来。。。。。。。

于是只好规定区间最低高度等于区间高度时才有效,实际查询时可能遍历到所有的叶节点,效率好像很低的样子,然后加一个强剪枝,即查询高度小于当前区间最低高度时直接返回0,然后就A了,感觉和花神游历各国里面的那个剪枝很像。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100000+5;
struct Node{
	int l,r,mi,h;
	bool mark;
}tr[N*4];
inline void pushup(int o){
	tr[o].mi=min(tr[o<<1].mi,tr[o<<1|1].mi);
}
void build(int o,int l,int r){
	tr[o].l=l;tr[o].r=r;
	tr[o].mi=tr[o].h=0;tr[o].mark=false;
	if(l!=r){
		int m=l+r>>1;
		build(o<<1,l,m);build(o<<1|1,m+1,r);
	}
}
void pushdown(int o){
	if(tr[o].mark){
		tr[o<<1].mark=tr[o<<1|1].mark=true;
		tr[o].mark=false;
		tr[o<<1].h=tr[o<<1].mi=tr[o<<1|1].h=tr[o<<1|1].mi=tr[o].h;
	}
}
int update(int o,int a,int b,int h){
	if(h<tr[o].mi)return 0;
	int l=tr[o].l,r=tr[o].r;
	if((tr[o].h==tr[o].mi&&tr[o].mi)||l==r){
		tr[o].h=tr[o].mi=h;
		tr[o].mark=1;
		return r-l+1;
	}
	else{
		pushdown(o);
		int m=l+r>>1,ans;
		if(b<=m)ans=update(o<<1,a,b,h);
		else if(m<a)ans=update(o<<1|1,a,b,h);
		else ans=update(o<<1,a,m,h)+update(o<<1|1,m+1,b,h);
		pushup(o);
		return ans;
	}
}
int main(){
	int T,n;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		build(1,1,100000-1);
		int l,r,h,ans=0;
		while(n--){
			scanf("%d%d%d",&l,&r,&h);
			ans+=update(1,l,r-1,h);
		}
		printf("%d\n",ans);
	}
	return 0;
}


你可能感兴趣的:(UVA 1232 - SKYLINE)