
注意点:
- 线段树中使用获取具体长度时右端点应当+1,向线段树内插入值时右端点应当-1.(区间覆盖线段树)
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int MAXN=2e6;
struct Line{
ll x1,x2,y;
bool type;
bool operator <(Line another)const{
return y<another.y;
}
}lines[MAXN];
int lineCnt=0;
struct Node{
int l,r;
ll len,cnt;
}tr[MAXN];
void build(int p,int l,int r){
tr[p].l=l,tr[p].r=r;
if(l==r)return;
int mid=(l+r)>>1;
build(p<<1,l,mid);
build((p<<1)|1,mid+1,r);
}
ll a[MAXN];//离散化
void pushup(int p){
if(tr[p].cnt){
tr[p].len=a[tr[p].r+1]-a[tr[p].l];
}else{
tr[p].len=tr[p<<1].len+tr[(p<<1)|1].len;
}
}
void change(int p,int l,int r,int val){
if(tr[p].l>=l&&tr[p].r<=r){
tr[p].cnt+=val;
pushup(p);
return;
}
int mid=(tr[p].l+tr[p].r)>>1;
if(l<=mid)change(p<<1,l,r,val);
if(r>mid)change((p<<1)|1,l,r,val);
pushup(p);
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
ll x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
lines[++lineCnt].x1=x1,lines[lineCnt].x2=x2;
lines[lineCnt].y=y1,lines[lineCnt].type=0;
lines[++lineCnt].x1=x1,lines[lineCnt].x2=x2;
lines[lineCnt].y=y2,lines[lineCnt].type=1;
a[i]=x1,a[i+n]=x2;
}
sort(a+1,a+2*n+1);
int cnt=unique(a+1,a+2*n+1)-a-1;//离散化
sort(lines+1,lines+2*n+1);
build(1,1,cnt-1);
ll ans=0;
for(int i=1;i<=2*n;i++){
Line nowLine=lines[i];
if(i>1)ans+=tr[1].len*(lines[i].y-lines[i-1].y);
if(nowLine.type){//消失
change(1,lower_bound(a+1,a+cnt+1,nowLine.x1)-a,lower_bound(a+1,a+cnt+1,nowLine.x2)-a-1,-1);
}else{//出现
change(1,lower_bound(a+1,a+cnt+1,nowLine.x1)-a,lower_bound(a+1,a+cnt+1,nowLine.x2)-a-1,1);
}
}
cout<<ans<<endl;
return 0;
}