题目大意:求矩形面积的并
思路:按y轴排序,然后将x投影到线段树上做一个线段覆盖问题即可
注意:为了避免重复,线段坐标右端点是开区间,更新时需要加上1
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=2e2+10;
typedef long long ll;
struct Line {
double x1,x2,h;
int f;
bool operator < (const Line &rhs) const {
return rhs.h>h;
}
Line(double x1=0,double x2=0,double h=0,int f=0):x1(x1),x2(x2),h(h),f(f){}
}L[N];
struct Node{
int l,r,cnt ;double len;
}tr[N<<2];
int n,kase=0; double tmp[N];
void build(int x,int l,int r)
{
tr[x].l=l;tr[x].r=r;tr[x].len=tr[x].cnt=0;
if(l==r) {return ;}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
}
void pushup(int x)
{
int l=tr[x].l,r=tr[x].r;
if(tr[x].cnt)
tr[x].len=tmp[r+1]-tmp[l];
else if(l==r)
tr[x].len=0;
else
tr[x].len=tr[x<<1].len+tr[x<<1|1].len;
}
void update(int x,int ql,int qr,int delta)
{
int l=tr[x].l,r=tr[x].r,mid=(l+r)>>1;
if(ql==tr[x].l&&qr==tr[x].r) {
tr[x].cnt+=delta;
pushup(x);
return ;
}
if(qr<=mid) update(x<<1,ql,qr,delta);
else if(ql>mid) update(x<<1|1,ql,qr,delta);
else {
update(x<<1,ql,mid,delta);
update(x<<1|1,mid+1,qr,delta);
}
pushup(x);
}
int main()
{
while(scanf("%d",&n)&&n){
for(int i=0;i<n;i++) {
double x1,x2,y1,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
L[i*2]=Line(x1,x2,y1,1); tmp[i*2]=x1;
L[i*2+1]=Line(x1,x2,y2,-1); tmp[i*2+1]=x2;
}
sort(L,L+2*n);
sort(tmp,tmp+2*n);
int sz=unique(tmp,tmp+2*n)-tmp;
build(1,0,sz-1);
double ans=0.0;
for(int i=0;i<n*2-1;i++) {
int l=lower_bound(tmp,tmp+sz,L[i].x1)-tmp;
int r=lower_bound(tmp,tmp+sz,L[i].x2)-tmp-1;
update(1,l,r,L[i].f);
ans+=(tr[1].len*(L[i+1].h-L[i].h));
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++kase,ans);
}
return 0;
}