Description
Input
The input file is terminated by a line containing a single 0. Don't process it.
Output
Output a blank line after each test case.
Sample Input
2
10 10 20 20
15 15 25 25.5
0
Sample Output
Test case #1
Total explored area: 180.00
題目大意:給定每個矩形的對角線的兩個端點,讓你求這些矩形的面積的並集,即重疊的不能重複計算
題目分析:這題就是典型的線段樹求面積並
離散化:對所有節點的Y進行升序排序,然後以Y的位置建樹,就是指,在線段樹裏面,左右節點的實際意義就是指這個線段在Y的升序數組裏的位置,但是我們把lf,rf賦值爲這個線段左右端點的具體值,這就是離散化
建樹的細節:樹的每個節點有lf,rf,cover,lenth,分別指這個節點所表示的線段的左端點,右端點,被覆蓋的次數(在這裏覆蓋的次數是爲了區分重疊矩形的情況下,高度的正確存取,因爲一個矩形對Y軸的覆蓋是以他的左邊開始,右邊結束的,所以當插入左邊的時候,我們把cover+1,右邊的時候把cover-1,說明這個矩形對Y的覆蓋已經結束,計算下一個矩形時,不會錯誤的把我這個矩形的高度當作下一個矩形的高度),lenth指這個區間被矩形覆蓋的長度即矩形的實際高度;插入的時候,先把存放節點的數組,對X進行升序排序,然後順次插入,分別計算
#include <stdio.h>
#include <algorithm>
using namespace std;
double x1,y1,x2,y2,ym[1111];
struct tree
{
double lf,rf,lenth;
int cover;
}s[4444]; //樹節點定義
struct node
{
double x,y1,y2;
int flag;
}t[4444]; //存放矩形左,右邊的節點
int cmp1(double x,double y)
{
return x < y;
}
int cmp2(node a,node b)
{
return a.x < b.x;
}
void len(int n)
{
if(s[n].cover>0)
s[n].lenth=s[n].rf-s[n].lf;
else
s[n].lenth=s[2*n+1].lenth+s[2*n].lenth;
}
int Build(int x,int y,int num)
{
s[num].lf=ym[x];
s[num].rf=ym[y];
s[num].lenth=s[num].cover=0;
if(x+1==y) return 0;
int mid=(x+y)/2;
Build(x,mid,num+num);
Build(mid,y,num+num+1);
}
int Update(int num,node n)
{
if(s[num].lf==n.y1 && s[num].rf==n.y2)
{
s[num].cover+=n.flag;
len(num);
return 0;
}
if(n.y1>=s[num+num].rf) Update(num+num+1,n);
else if(n.y2<=s[num+num+1].lf) Update(num+num,n);
else
{
node vs=n;
vs.y2=s[num+num].rf;
Update(num+num,vs);
vs=n;
vs.y1=s[num+num+1].lf;
Update(num+num+1,vs);
}
len(num); //往上更新線段被覆蓋的實際長度,如果節點的cover>0,
//該區間節點的被覆蓋就是區間的整體程度;
//否則,該區間節點的被覆蓋等於左右節點被覆蓋長度的和
}
int main()
{
int cas,i,j,k=1;
double sum;
while(scanf("%d",&cas) && cas)
{
for(j=i=1;i<=cas;i++,j+=2)
{
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
ym[j]=y1;
t[j].x=x1;
t[j].y1=y1;
t[j].y2=y2;
t[j].flag=1;
ym[j+1]=y2;
t[j+1].x=x2;
t[j+1].y1=y1;
t[j+1].y2=y2;
t[j+1].flag=-1;
}
sort(ym+1,ym+j,cmp1);
sort(t+1,t+j,cmp2);
Build(1,j-1,1);
Update(1,t[1]);
sum=0;
for(i=2;i<j;i++)
{
sum+=(t[i].x-t[i-1].x)*s[1].lenth;//每插入完一個點,就以它後繼的點求面積
Update(1,t[i]);
}
printf("Test case #%d\n",k);
printf("Total explored area: %.2lf\n\n",sum);
k++;
}
return 0;
}