Description
给出N个矩形,N<=10000.其坐标不超过10^9.求其面积并
Input
先给出一个数字N,代表有N个矩形. 接下来N行,每行四个数,代表矩形的坐标.
Output
输出面积并
经典的线段树维护扫描线
令扫描线平行于y轴沿x轴正方向移动,线段树维护扫描线上被矩形覆盖的长度(实际维护的是当前扫描线上被矩形覆盖层数最少的层数和相应的长度,即维护区间+-1和区间最小值和区间最小值个数)
#include<cstdio>
#include<algorithm>
typedef long long i64;
char buf[],*ptr=buf-;
int _(){
int x=,f=,c=*++ptr;
while(c<)c=='-'&&(f=-),c=*++ptr;
while(c>)x=x*+c-,c=*++ptr;
return x*f;
}
int n,_L,_R,A;
int rs[][];
struct node{
node*l,*r;
int mn,mc,av;
void dn(){
if(!av)return;
l->mn+=av;
l->av+=av;
r->mn+=av;
r->av+=av;
av=;
}
void up(){
mn=l->mn;
mc=l->mc;
if(mn>r->mn)mn=r->mn,mc=r->mc;
else if(mn==r->mn)mc+=r->mc;
}
void inc(int L,int R){
if(_L<=L&&R<=_R){
mn+=A;
av+=A;
return;
}
dn();
int M=L+R>>;
if(_L<=M)l->inc(L,M);
if(_R>M)r->inc(M+,R);
up();
}
}ns[],*np=ns,*rt;
int ys[],yp=;
node*build(int L,int R){
node*w=np++;
w->mc=ys[R+]-ys[L];
if(L!=R){
int M=L+R>>;
w->l=build(L,M);
w->r=build(M+,R);
}
return w;
}
struct event{
int x,y1,y2,t;
}e[],*ep=e;
bool operator<(const event&a,const event&b){
return a.x<b.x;
}
int main(){
fread(buf,,,stdin);
n=_();
for(int i=;i<n;++i){
for(int j=;j<;++j)rs[i][j]=_();
ys[yp++]=rs[i][];
ys[yp++]=rs[i][];
}
std::sort(ys,ys+yp);
yp=std::unique(ys,ys+yp)-ys;
for(int i=;i<n;++i){
rs[i][]=std::lower_bound(ys,ys+yp,rs[i][])-ys;
rs[i][]=std::lower_bound(ys,ys+yp,rs[i][])-ys-;
*(ep++)=(event){rs[i][],rs[i][],rs[i][],};
*(ep++)=(event){rs[i][],rs[i][],rs[i][],-};
}
rt=build(,yp-);
std::sort(e,ep);
ep->x=0x7fffffff;
int px=e->x,h=ys[yp-]-ys[];
i64 ans=;
for(event*p1=e,*p2=e;p1!=ep;p1=p2){
ans+=i64(p1->x-px)*(h-(rt->mn?:rt->mc));
px=p1->x;
while(p1->x==p2->x)++p2;
while(p1!=p2){
_L=p1->y1,_R=p1->y2,A=p1->t;
if(_L<=_R)rt->inc(,yp-);
++p1;
}
}
printf("%lld",ans);
return ;
}