线段树+扫描线 hdu1542 Atlantis
矩形的坐标不一定是整数
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <set>
#define inf 0x3f3f3f3f
#define ll long long
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int MX=105;
int N,cnt=0,rt=1;
double v[MX<<1];
struct T{ //建立线段树
double l,r;
int cover;
double len;
}tree[MX<<4];
struct Line{ //存储从左到右的扫描线,state存储矩形的左边还是右边
double x;
double y1,y2;
int state;
bool operator <(Line l){return x<l.x;} //重写 '<',排序需要
}line[MX<<1];
inline void pushup(int rt){
if(tree[rt].cover) tree[rt].len=tree[rt].r-tree[rt].l;
else
tree[rt].len=tree[ls].len+tree[rs].len;
}
void build(int l,int r,int rt){
tree[rt].l=v[l],tree[rt].r=v[r];
if(r-l<=1) return;
int mid=(l+r)>>1;
build(l,mid,ls);
build(mid,r,rs);
}
void modify(double fl,double fr,int state,int rt){
double l=tree[rt].l,r=tree[rt].r;
if(fl<=l&&r<=fr){
tree[rt].cover+=state;
pushup(rt);
return;
}
if(fl<tree[ls].r) modify(fl,fr,state,ls);
if(fr>tree[rs].l) modify(fl,fr,state,rs);
pushup(rt);
}
int main()
{
while(scanf("%d",&N)==1){
if(N==0) return 0;
int n=N<<1;
double x1,y1,x2,y2;
for(int i=1;i<=N;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
v[i]=y1,v[i+N]=y2;
line[i]=(Line){x1,y1,y2,1};
line[i+N]=(Line){x2,y1,y2,-1};
}
sort(line+1,line+1+n);
sort(v+1,v+1+n);
build(1,n,rt);
double ans=0;
for(int i=1;i<=n;i++){
ans+=tree[1].len*(line[i].x-line[i-1].x);
modify(line[i].y1,line[i].y2,line[i].state,rt);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++cnt,ans);
}
}