做法:按高度排序之后,直接映射到数组上计算好了。注意LL 用的要及时,WA了许久..
#include<cstdio> #include<cstring> #include<algorithm> #define left l,m,x<<1 #define right m+1,r,x<<1|1 #define LL __int64 const int LMT=160003; using namespace std; int myx[LMT],cnt,seg[LMT]; int cov[LMT<<2]; LL ans; //区间覆盖要考虑1,因为这是连续空间中的问题,更严格 //加一的策略是在本身考虑的问题也是离散的,如贴海报那一题 //还有一种是把区间变成左闭右开的,这个只能在可以看见整个区间的时候用 //这个还有一种方法是哪个加一个SUM数组记录区间长度 struct wall { int a,b,h; bool operator<(const wall y)const { return h<y.h; } }w[40004]; void init(void) { memset(seg,-1,sizeof(seg)); memset(cov,-1,sizeof(cov)); cnt=0;ans=0; } void cut(int x) { if(cov[x]!=-1) { cov[x<<1]=cov[x<<1|1]=cov[x]; cov[x]=-1; } } void update(int op,int L,int R,int l,int r,int x) { if(L<=l&&r<=R) { cov[x]=op; return; } cut(x); int m=(l+r)>>1; if(L<=m)update(op,L,R,left); if(R>m)update(op,L,R,right); } void query(int l,int r,int x) { if(cov[x]!=-1) { int i; for(i=l;i<=r;i++)seg[i]=cov[x]; return; } if(r==l)return; cut(x); int m=(l+r)>>1; query(left); query(right); } int myfind(int x) { int m,l=0,r=cnt-1; while(l<=r) { m=(l+r)>>1; if(myx[m]==x)return m; if(myx[m]<x)l=m+1; else r=m-1; } return -1; } int main(void) { int n,i,t,j; while(~scanf("%d",&n)) { init(); for(i=0;i<n;i++) { scanf("%d%d%d",&w[i].a,&w[i].b,&w[i].h); myx[cnt++]=w[i].a;myx[cnt++]=w[i].b; } myx[cnt++]=(int)1e9+2; sort(w,w+n); sort(myx,myx+cnt); t=1; for(i=1;i<cnt;i++) if(myx[i]!=myx[i-1])myx[t++]=myx[i]; cnt=t; for(i=1;i<t;i++) if(myx[i]-myx[i-1]>1)myx[cnt++]=myx[i-1]+1; sort(myx,myx+cnt); for(i=0;i<n;i++) { w[i].a=myfind(w[i].a); w[i].b=myfind(w[i].b); update(i,w[i].a,w[i].b-1,0,cnt-1,1); } query(0,cnt-1,1); for( i=0;i<cnt;) if(seg[i]!=-1) { j=i; while(j<cnt&&seg[i]==seg[j])j++; ans+=(myx[j]-myx[i])*1LL*w[seg[i]].h; i=j; } else i++; printf("%I64d\n",ans); } return 0; }