求相交面积 为奇数次的面积总和。
就是随便改一下原来扫描线的代码。 ,
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5;
struct node{
int y,x1,x2;
int flag;
bool operator < (const node &now) const {
return y < now.y;
}
}g[N];
struct segtree{
int ll,rr;
long long w;
int l,r,a,b,c,cover;
int cal_mid(){
return (a + b) / 2;
}
}f[N*2];
int t,n,zz;
int x[N],xx,yy;
void build(int p, int a, int b){
f[p].a = a; f[p].b = b;
f[p].ll = x[a]; f[p].rr = x[b];
f[p].w = f[p].cover = f[p].c =0;
if (a + 1 == b) return;
int m = f[p].cal_mid();
t++; f[p].l = t; build(t,a,m);
t++; f[p].r = t; build(t,m,b);
return;
}
void pushup(int p){
if (f[p].a + 1 == f[p].b) {
if (f[p].cover % 2 == 1) f[p].w = f[p].rr - f[p].ll;
else f[p].w = 0;
}
else{
f[p].w = f[f[p].l].w + f[f[p].r].w;
if (f[p].cover % 2 == 1)
f[p].w = (f[p].rr - f[p].ll) - f[p].w;
}
return;
}
void Insert(int p){
if ((xx <= f[p].ll && yy >= f[p].rr ) || f[p].a + 1 == f[p].b ){
f[p].cover = f[p].cover + zz;
pushup(p);
return;
}
if (xx < f[f[p].l].rr) Insert(f[p].l);
if (yy > f[f[p].r].ll) Insert(f[p].r); // 这里就要根据实际情况来判断了。
pushup(p);
return;
}
int main() {
scanf("%d",&n);
int x1,x2,y1,y2;
int tt = 1;
for (int i = 1; i <= n; i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
g[tt].x1 = x1; g[tt].x2 = x2; g[tt].flag = 1; x[tt] = x1; g[tt++].y = y1;
g[tt].x1 = x1; g[tt].x2 = x2; g[tt].flag = -1; x[tt] = x2; g[tt++].y = y2;
}
sort(g + 1, g + tt); //离散化
sort(x + 1, x + tt); tt--;
t = 1;
build(1,1,tt); //建树, 1 到 n 这种求区间长度的线段树,暂且理解为全部都是闭区间吧。
xx = g[1].x1; yy = g[1].x2; zz = 1;
Insert(1);
long long ans = 0;
for (int i = 2; i <= tt; i++){
xx = g[i].x1; yy = g[i].x2; zz = g[i].flag;
ans += 1ll*f[1].w * (g[i].y - g[i - 1].y);
// printf("%d %d %d\n",i,f[1].w,ans);
Insert(1);
// printf("\n");
}
printf("%lld\n",ans);
return 0;
}