矩陣重疊面積計算 線段樹hdu1542
阿新 • • 發佈:2017-09-26
val space contains number starting vol nta digi ron
Input
The input file consists of several test cases. Each test case starts with a line containing a single integer n (1<=n<=100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0<=x1<x2<=100000;0<=y1<y2<=100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.
The input file is terminated by a line containing a single 0. Don’t process it.
Output
For each test case, your program should output one section. The first line of each section must be “Test case #k”, where k is the number of the test case (starting with 1). The second one must be “Total explored area: a”, where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point.
Output a blank line after each test case.
Sample Input
2
10 10 20 20
15 15 25 25.5
0
Atlantis
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 14378 Accepted Submission(s): 5931
The input file is terminated by a line containing a single 0. Don’t process it.
Output a blank line after each test case.
Sample Output Test case #1 Total explored area: 180.00 轉載
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lz 2*u,l,mid #define rz 2*u+1,mid+1,r const int maxn=4222; double sum[maxn]; int flag[maxn]; double X[maxn]; struct Node { double lx, rx, y; int s; Node(){}; Node(double lx_, double rx_, double y_, int s_) { lx=lx_, rx=rx_, y=y_, s=s_; } bool operator <(const Node &S) const { return y<S.y; } }line[maxn]; int find(double tmp, int n) { int l=1, r=n, mid; while(l<=r) { mid=(l+r)>>1; if(X[mid]==tmp) return mid; else if(X[mid]<tmp) l=mid+1; else r=mid-1; } } void push_up(int u, int l, int r) { if(flag[u]) sum[u]=X[r+1]-X[l]; else if(l==r) sum[u]=0; else sum[u]=sum[2*u]+sum[2*u+1]; } void Update(int u, int l, int r, int tl, int tr, int c) { if(tl<=l&&r<=tr) { flag[u]+=c; push_up(u,l,r); return ; } int mid=(l+r)>>1; if(tr<=mid) Update(lz,tl,tr,c); else if(tl>mid) Update(rz,tl,tr,c); else { Update(lz,tl,mid,c); Update(rz,mid+1,tr,c); } push_up(u,l,r); } int main() { int n,tcase=0; while(cin >> n,n) { int num=0; memset(flag,0,sizeof(flag)); memset(sum,0,sizeof(sum)); for(int i=0; i<n; i++) { double x1,x2,y1,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); line[++num]=Node(x1,x2,y1,1); X[num]=x1; line[++num]=Node(x1,x2,y2,-1); X[num]=x2; } sort(X+1,X+num+1); sort(line+1,line+num+1); int k=2*n; double ans=0; for(int i=1; i<num; i++) { int l=find(line[i].lx,k); int r=find(line[i].rx,k)-1;//r之所以要減一是因為防止搜索分叉的時候出現其余的節點都到左節點,而只有一個節點到右節點,如果減一後再配合查詢時的+1那麽就可以解決這個問題了,因為如果要有分叉的話,他實際上是右子樹的第一個減去左子樹開始的地方,如果沒有分叉,那麽直接+1再減也是滿足的 Update(1,1,k,l,r,line[i].s); ans+=sum[1]*(line[i+1].y-line[i].y); } printf("Test case #%d\n",++tcase); printf("Total explored area: %.2lf\n\n",ans); } return 0; }
矩陣重疊面積計算 線段樹hdu1542