这题写了三四天,真是写郁闷了,后来才发现自己这题写2B了,唉,桑心。
题意:在地平线上依次建n座建筑物。建筑物的修建按照从后往前的顺序,修建完一座建筑物以后,统计它在多长的部分是最高的,并把这个长度称为“覆盖度”,最后输出总的覆盖度。
思路:刚开始的时候,我的思路比较简单,就是记录每个区间最高的建筑物有多高,如果要修建的这个建筑物的高度比这个区间最高的建筑物还高,那么这个结果就要加上这个区间的长度,否则就接着找下去。但是这样的话会有问题,将一个区间分为两部分的时候,分开的那部分很难计算,比如区间[1,6]分为两个区间[1,3]、[4,6],那么[3,4]这个区间的值就不好计算了,当时写的时候加了好多特判,搞得乱七八糟的,还是各种wrong。其实这个问题换个角度看会容易很多:对于每个单位区间,比如[3,3],我们记录的值可以看做从3到4之前的这个区间中建筑物的最大值,这样的话,每次更新的时候更新的就是l~r-1的这段区间,查询按上面的方法去搞就行了,当这个区间最高的建筑物比要修建的建筑物低,那么直接在sum中加上区间的长度r-l+1即可。
代码:
#include <iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #define inf 0x3f3f3f3f #define Inf 0x3FFFFFFFFFFFFFFFLL #define eps 1e-9 #define pi acos(-1.0) using namespace std; //typedef long long ll; const int maxn=100000+10; const int N=100000; int hightv[maxn<<2],setv[maxn<<2]; bool flag[maxn<<2]; int sum; void PushUp(int rt) { int ls=rt<<1,rs=rt<<1|1; hightv[rt]=max(hightv[ls],hightv[rs]); flag[rt]=(hightv[ls]==hightv[rs])&&flag[ls]&&flag[rs]; } void PushDown(int rt) { if(setv[rt]>=0) { int ls=rt<<1,rs=rt<<1|1; if(setv[rt]>=hightv[ls]) { hightv[ls]=setv[rt]; flag[ls]=true; } if(setv[rt]>=hightv[rs]) { hightv[rs]=setv[rt]; flag[rs]=true; } setv[ls]=max(setv[ls],setv[rt]); setv[rs]=max(setv[rs],setv[rt]); setv[rt]=-1; } } void build(int l,int r,int rt) { hightv[rt]=0; setv[rt]=-1; flag[rt]=true; if(l==r) return; int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); } void Update(int v,int L,int R,int l,int r,int rt) { if(l>=L&&r<=R&&hightv[rt]<=v) { sum+=(r-l+1); setv[rt]=hightv[rt]=v; flag[rt]=true; return; } if(l>=L&&r<=R&&hightv[rt]>v&&flag[rt]) { return; } PushDown(rt); int m=(l+r)>>1; int ls=rt<<1,rs=rt<<1|1; if(m>=L) Update(v,L,R,l,m,ls); if(m<R) Update(v,L,R,m+1,r,rs); PushUp(rt); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n,l,r,h; int t; while(cin>>t) { if(t==0) break; while(t--) { cin>>n; build(1,N,1); int res=0; for(int i=0;i<n;++i) { cin>>l>>r>>h; sum=0; Update(h,l,r-1,1,N,1); res+=sum; } cout<<res<<endl; } } return 0; }