题意: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);
}
}