http://poj.org/problem?id=3277
经典的矩形面积并 对y离散后 建树 用拆点后的以x为顺序 依次更新
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<ctime> #include<queue> #include<cstring> #include<set> #include<cmath> #include<algorithm> #define LL long long using namespace std; const int N=40005; struct node { int l,r; LL H;//这个高度主要是用来查找的 LL h;//这一段的最高度 int cover;//被覆盖次数 }mem[N*4]; LL Y[N*2];//高度 struct poin { int k; LL x; LL h; }point[N*2];//拆点 k 表示左点 还是右点 bool cmp(poin a,poin b) { if(a.x==b.x) return a.h<b.h; return a.x<b.x; } LL Labs(LL x) { if(x<0) return -x; return x; } LL Lmax(LL x,LL y) { if(x>y) return x; return y; } void build(int x,int l,int r) { mem[x].cover=0; mem[x].l=l; mem[x].r=r; mem[x].h=0; if(l==r) { mem[x].H=Y[l]; return ; } int mid=(l+r)>>1; build(x*2,l,mid); build(x*2+1,mid+1,r); mem[x].H=Lmax(mem[x*2].H,mem[x*2+1].H);//更新最高度 } void add(int x,int k) { if(mem[x].l==mem[x].r) { mem[x].cover+=point[k].k;//更新cover if(mem[x].cover>0)//大于0 为有覆盖 所以高度为 H 否则为0 mem[x].h=mem[x].H; else mem[x].h=0; return ; } if(Labs(point[k].h)<=mem[x*2].H) add(x*2,k); else add(x*2+1,k); mem[x].h=Lmax(mem[x*2].h,mem[x*2+1].h);//更新 } int main() { // freopen("data.txt","r",stdin); int n; while(scanf("%d",&n)!=EOF) { for(int i=0;i<n;++i) { scanf("%I64d %I64d %I64d",&point[i].x,&point[i+n].x,&point[i].h); point[i+n].h=point[i].h; point[i].k=1; point[i+n].k=-1; Y[i]=point[i].h; } sort(Y,Y+n); sort(point,point+n*2,cmp); build(1,0,n-1);//对排序后的高度进行建树 add(1,0); LL ans=0; for(int i=1;i<2*n;++i) { ans+=(point[i].x-point[i-1].x)*mem[1].h;//更新面积 add(1,i); } cout<<ans<<endl; } return 0; }