http://poj.org/problem?id=1389
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 2772 | Accepted: 1409 |
Description
Assume that the contour of their union is defi ned by a set S of segments. We can use a subset of S to construct simple polygon(s). Please report the total area of the polygon(s) constructed by the subset of S. The area should be as large as possible. In a 2-D xy-plane, a polygon is defined by a finite set of segments such that every segment extreme (or endpoint) is shared by exactly two edges and no subsets of edges has the same property. The segments are edges and their extremes are the vertices of the polygon. A polygon is simple if there is no pair of nonconsecutive edges sharing a point.
Example: Consider the following three rectangles:
rectangle 1: < (0, 0) (4, 4) >,
rectangle 2: < (1, 1) (5, 2) >,
rectangle 3: < (1, 1) (2, 5) >.
The total area of all simple polygons constructed by these rectangles is 18.
Input
Output
Sample Input
0 0 4 4 1 1 5 2 1 1 2 5 -1 -1 -1 -1 0 0 2 2 1 1 3 3 2 2 4 4 -1 -1 -1 -1 -1 -1 -1 -1
Sample Output
18 10
Source
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1000+10; struct node { int l,r; int lf,rf,width; int cover; }mem[N*6];//線段樹 lf rf 分別爲邊界 cover 爲覆蓋情況 width 爲覆蓋的寬度 struct poin { int x; //記錄x座標 int y1,y2; //y1,y2用來記錄平行y軸的線段的兩個端點, int k; //標記是左邊的邊還是右邊的邊,拆點 k爲-1代表左點 1 代表右點 }point[N*2]; int Y[N*2]; bool cmp(poin a,poin b) //排序(x按照從小到大,只需要把x排序) { return a.x<b.x; } void build(int x,int l,int r)//建樹 { mem[x].l=l; mem[x].r=r; mem[x].lf=Y[l]; mem[x].rf=Y[r]; mem[x].cover=mem[x].width=0; if(l+1==r) //葉子結點 return ; int mid=(l+r)>>1; build(x*2,l,mid);//端點模型,不是格子模型 build(x*2+1,mid,r); } void find(int x)//更新此處的覆蓋寬度 { if(mem[x].cover>0) //完全覆蓋(右點則要完全覆蓋) { mem[x].width=mem[x].rf-mem[x].lf; //求出長度 return ; } if(mem[x].l+1==mem[x].r) // 葉子節點,wiith 爲 0 mem[x].width=0; else//非葉子節點即爲下面子區間的覆蓋綜合,注意由於插入的遞歸性保證了此等式的執行順序的正確性 mem[x].width=mem[x*2].width+mem[x*2+1].width; } void add(int x,int k)//加入一個點k的影響 { if(mem[x].lf>=point[k].y1&&mem[x].rf<=point[k].y2)//全部覆蓋 ;//直接比較實際值,顯示出了cover和標記爲1,-1的作用 { mem[x].cover+=point[k].k; find(x); return ; } int mid=(mem[x].l+mem[x].r)>>1; if(Y[mid]<=point[k].y1)//查看 需要怎樣往下更新 { add(x*2+1,k); } else if(Y[mid]>=point[k].y2) { add(x*2,k); } else { add(x*2,k); add(x*2+1,k); } find(x); } int main() { //freopen("data.txt","r",stdin); int x1,y1,x2,y2; while(1) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(x1==-1&&y1==-1&&x2==-1&&y2==-1) break; int I=0; point[I].x=x1; //把座標映射到數組裏(離散化) point[I].y1=y1; point[I].y2=y2; point[I].k=1; Y[I]=y1; ++I; point[I].x=x2; point[I].y1=y1; point[I].y2=y2; point[I].k=-1; Y[I]=y2; ++I; while(1){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(x1==-1&&y1==-1&&x2==-1&&y2==-1) break; point[I].x=x1; //把座標映射到數組裏(離散化) point[I].y1=y1; point[I].y2=y2; point[I].k=1; Y[I]=y1; ++I; point[I].x=x2; point[I].y1=y1; point[I].y2=y2; point[I].k=-1; Y[I]=y2; ++I; } sort(Y,Y+I); //縱座標排序(小到大) sort(point,point+I,cmp); build(1,0,I-1); //建樹 add(1,0); int ans=0; for(int i=1;i<I;++i) { //cout<<i<<endl; ans+=(mem[1].width*(point[i].x-point[i-1].x));//每次用兩個x座標差 × 當前覆蓋寬度 //cout<<ans<<endl; add(1,i);//cout<<"TTT"<<endl; } printf("%d\n",ans); } return 0; }