UVALive 4108 - SKYLINE(线段树区间更新)
题目链接 https://cn.vjudge.net/problem/UVALive-4108
【题意】
在地平线上依次建造n座建筑物,建筑物的修建按照从后往前的顺序,新建筑物可能会挡住一些老建筑物。在修建完一座建筑物后,统计它在多长的部分是最高的(可以和其他建筑物并列最高),把这个长度称为该建筑的“覆盖度”
【输入格式】
多组输入,第一行为数据组数。每组数据第一行为建筑物个数n(1<=n<=1e5)以下n行按照先后顺序给出n座建筑物的的左右边界和高度l,r,h(0 < l < r < 1e5,0 < h<=1e9)
【输出格式】
对每组数据,输出所有建筑物的总覆盖度
【思路】
对整个区间建立一个线段树,维护最大值和最小值,在每次更新的时候,如果当前区间的最小值比建筑物的高度还大,那么就不用更新区间的值了,如果当前区间的最大值小于等于建筑物高度,那么答案就要加上这一段区间的长度,并把这段区间更新成建筑物的高度
#include<bits/stdc++.h>
#define node tree[id]
#define lson tree[id<<1]
#define rson tree[id<<1|1]
using namespace std;
const int maxn=100050;
int n;
struct Tree{
int left,right;
int maxv,minv,lazy;
}tree[maxn<<2];
void pushup(int id){
node.maxv=max(lson.maxv,rson.maxv);
node.minv=min(lson.minv,rson.minv);
}
void pushdown(int id){
if(node.lazy && node.left!=node.right){
lson.lazy=node.lazy;
lson.maxv=lson.minv=node.lazy;
rson.lazy=node.lazy;
rson.maxv=rson.minv=node.lazy;
node.lazy=0;
}
}
void build(int id,int le,int ri){
node.left=le;
node.right=ri;
node.lazy=0;
node.maxv=node.minv=0;
if(le==ri) return;
int mid=(le+ri)>>1;
build(id<<1,le,mid);
build(id<<1|1,mid+1,ri);
}
int update(int id,int le,int ri,int val){
if(node.left==le && node.right==ri && node.minv>val) return 0;
if(node.left==le && node.right==ri && node.maxv<=val){
if(node.maxv<val){
node.lazy=val;
node.maxv=node.minv=val;
}
return ri-le+1;
}
pushdown(id);
int ans=0;
int mid=(node.left+node.right)>>1;
if(ri<=mid) ans=update(id<<1,le,ri,val);
else if(le>mid) ans=update(id<<1|1,le,ri,val);
else ans=update(id<<1,le,mid,val)+update(id<<1|1,mid+1,ri,val);
pushup(id);
return ans;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int ans=0;
build(1,1,100000);
scanf("%d",&n);
for(int i=0;i<n;++i){
int x,y,h;
scanf("%d%d%d",&x,&y,&h);
ans+=update(1,x,y-1,h);
}
printf("%d\n",ans);
}
scanf("%d",&T);
return 0;
}