题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542
题意:给出一些矩形,求面积并。
从左到右扫描,纵坐标排序后,按数组下标建树,插入纵线段端点再映射到原数,别的就没什么了。
参考代码:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<iomanip>
#include<stdio.h>
#include<math.h>
using namespace std;
#define clr(arr,val) memset(arr,val,sizeof(arr))
const int M = 105;
const double eps = 1e-7;
enum In{lt,rt};
int n,k;
double num_y[M*2];
struct rectangle{
double x1,y1,x2,y2;
}rec[M];
struct SegTree{
int count;
int amount,L,R,lv,rv;
double depth;
}Tree[M*8];
void Update(int,double,double);
void Build(int root,int L,int R){
Tree[root].amount = 0;
Tree[root].lv = Tree[root].rv = 0;
Tree[root].count = Tree[root].depth = 0;
Tree[root].L = L;
Tree[root].R = R;
if(L == R - 1) return ;
Build(root<<1,L,(L+R)/2);
Build((root<<1)+1,(L+R)/2,R);
}
void Insert(int root,double L,double R){
if(num_y[ Tree[root].L ] >= L-eps && num_y[ Tree[root].R ] <= R+eps){
Tree[root].count++;
Update(root,L,R);
}
else {
if(L < num_y[ (Tree[root].L+Tree[root].R)/2 ]){
Insert(root<<1,L,R);
Update(root,L,R);
}
if(R > num_y[ (Tree[root].L+Tree[root].R)/2 ]){
Insert((root<<1)+1,L,R);
Update(root,L,R);
}
}
}
void Delete(int root,double L,double R){
if(num_y[ Tree[root].L ] >= L-eps && num_y[ Tree[root].R ] <= R+eps){
Tree[root].count--;
Update(root,L,R);
}
else {
if(L < num_y[ (Tree[root].L+Tree[root].R)/2 ]){
Delete(root<<1,L,R);
Update(root,L,R);
}
if(R > num_y[ (Tree[root].L+Tree[root].R)/2 ]){
Delete((root<<1)+1,L,R);
Update(root,L,R);
}
}
}
void Update(int root,double L,double R){
if(Tree[root].count > 0){
Tree[root].depth = num_y[ Tree[root].R ] - num_y[ Tree[root].L ];
Tree[root].amount = 1;
Tree[root].lv = 1;
Tree[root].rv = 1;
Tree[root].amount = 1;
}
else if(Tree[root].L == Tree[root].R - 1) {
if(Tree[root].count == 0){
Tree[root].depth = 0;
Tree[root].amount = 0;
Tree[root].lv = 0;
Tree[root].rv = 0;
}
}
else if(Tree[root].count == 0){
Tree[root].rv = Tree[(root<<1)+1].rv;
Tree[root].lv = Tree[root<<1].lv;
Tree[root].depth = Tree[root<<1].depth + Tree[(root<<1)+1].depth;
Tree[root].amount = Tree[root<<1].amount + Tree[(root<<1)+1].amount
- Tree[root<<1].rv * Tree[(root<<1)+1].lv;
}
}
struct operation{
In in;
double x,lower_y,high_y;
}Event[M*4];
void input(){
for(int i = 0;i < n;++i){
cin>>rec[i].x1>>rec[i].y1>>rec[i].x2>>rec[i].y2;
}
}
void Hash(){
for(int i = 0;i < n;++i){
num_y[i*2] = rec[i].y1;
num_y[i*2+1] = rec[i].y2;
Event[i*2].in = lt;
Event[i*2].x = rec[i].x1;
Event[i*2].lower_y = rec[i].y1;
Event[i*2].high_y = rec[i].y2;
Event[i*2+1].in = rt;
Event[i*2+1].x = rec[i].x2;
Event[i*2+1].lower_y = rec[i].y1;
Event[i*2+1].high_y = rec[i].y2;
}
sort(num_y,num_y+n*2);
}
bool cmp(operation a,operation b){ return a.x < b.x; }
void solve(){
input();
Hash();
Build(1,0,n*2-1);
sort(Event,Event+n*2,cmp);
double ans = 0,len = 0;
int last_amount = 0,now_amount;
double last_depth = 0,now_depth = 0;
for(int i = 0;i < n*2;++i){
if(Event[i].in == lt)
Insert(1,Event[i].lower_y,Event[i].high_y);
else
Delete(1,Event[i].lower_y,Event[i].high_y);
now_amount = Tree[1].amount;
now_depth = Tree[1].depth;
ans += last_depth * (i?(Event[i].x-Event[i-1].x):0);
len += last_amount * 2 * (i?(Event[i].x-Event[i-1].x):0);
len += fabs(now_depth-last_depth);
last_amount = now_amount;
last_depth = now_depth;
}
cout<<"Test case #"<<++k<<endl<<"Total explored area: ";
cout<<fixed<<setprecision(2)<<ans<<endl<<endl;
//cout<<fixed<<setprecision(2)<<len<<endl;//矩形周长并
}
int main(){
k = 0;
while(cin>>n && n){
solve();
}
return 0;
}