题解:线段树扫描线求面积交,维护区间修改次数为0的和区间次数为奇数和偶数的,偶数的个数减去为0的个数就是面积交为偶数个矩阵。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e6+100;
struct Line{
ll y,x1,x2,v;
bool operator < (const Line&p) const{
return y<p.y;
}
}line[maxn*4];
ll px[maxn*4];
ll tree[maxn*4],laz[maxn*4],len[maxn*4][2];
int filp[maxn*4];
void push_up(int x,int l,int r){
if(laz[x]) tree[x]=px[r+1]-px[l];
else if(l==r) tree[x]=0;
else tree[x]=tree[x<<1]+tree[x<<1|1];
}
void add(int x,int l,int r,int lx,int rx,ll val){ //维护区间>0的个数
if(lx<=l&&rx>=r){
laz[x]+=val;
push_up(x,l,r);
return ;
}
int mid=(l+r)>>1;
if(lx<=mid) add(x<<1,l,mid,lx,rx,val);
if(rx>mid) add(x<<1|1,mid+1,r,lx,rx,val);
push_up(x,l,r);
}
void push_down(int x){
swap(len[x<<1][0],len[x<<1][1]);
swap(len[x<<1|1][0],len[x<<1|1][1]);
filp[x<<1]^=1; filp[x<<1|1]^=1;
filp[x]=0;
}
void update(int x,int l,int r,int lx,int rx){ //维护区间为偶数的
if(lx<=l&&rx>=r){
filp[x]^=1;
swap(len[x][0],len[x][1]);
return ;
}
if(filp[x]) push_down(x);
int mid=(l+r)>>1;
if(lx<=mid) update(x<<1,l,mid,lx,rx);
if(rx>mid) update(x<<1|1,mid+1,r,lx,rx);
len[x][0]=len[x<<1][0]+len[x<<1|1][0];
len[x][1]=len[x<<1][1]+len[x<<1|1][1];
}
void build(int x,int l,int r){
len[x][0]=px[r+1]-px[l];
if(l==r) return ;
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
}
int main(){
int n,cnt=0,tot=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
ll a,b,c,d;
scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
if(a==c||b==d) continue;
px[++tot]=a; px[++tot]=c;
line[++cnt]=Line{min(b,d),min(a,c),max(a,c),1};
line[++cnt]=Line{max(b,d),min(a,c),max(a,c),-1};
}
if(!cnt) {
cout<<0<<endl;
return 0;
}
sort(line+1,line+1+cnt);
sort(px+1,px+1+tot);
tot=unique(px+1,px+1+tot)-(px+1); px[tot+1]=px[tot];
build(1,1,tot); ll ans=0;
for(int i=1;i<=cnt-1;i++){
int x1=upper_bound(px+1,px+1+tot,line[i].x1)-(px+1);
int x2=upper_bound(px+1,px+1+tot,line[i].x2)-(px+1)-1;
update(1,1,tot,x1,x2);
add(1,1,tot,x1,x2,line[i].v);
ans+=(ll)(len[1][0]-(px[tot]-px[1]-tree[1]))*(ll)(line[i+1].y-line[i].y);
}
cout<<ans<<endl;
return 0;
}