扫描线

简析

扫过来求和

例题1

B. 【例题2】矩形面积并 - 「计算几何」第5章 扫描线 - 金牌导航 - 课程 - YbtOJ

统计覆盖$\geq$1时的和,可以用vector+sort(精度高,复杂度低),也可以用线段树

#include<bits/stdc++.h>
#define db double
using namespace std;

const int N=205,M=805;
int n,m,tot,t[M],ls[M],rs[M],id[N],mx,rt;
db fid1[N],fid2[N],c[M];
struct A{db x,y; }a[N];
vector<A>V[N],V1[N];
inline bool cmpx(int i,int j) {
	return a[i].x<a[j].x;
}
inline bool cmpy(int i,int j) {
	return a[i].y<a[j].y;
}

void bld(int &p) {
	t[p]=c[p]=0;
	if(ls[p]) bld(ls[p]);
	if(rs[p]) bld(rs[p]);
	p=0;
}
void add(int &p,int l,int r,int x,int y,int k) {
	if(x>y) return;
	if(!p) p=++tot;
	if(l==x&&r==y) {
		t[p]+=k;
		if(t[p]) c[p]=fid2[r]-fid2[l-1];
			else c[p]=c[ls[p]]+c[rs[p]];
		return;
	}
	int mid=l+r>>1;
	if(y<=mid) add(ls[p],l,mid,x,y,k);
		else if(x>mid) add(rs[p],mid+1,r,x,y,k);
			else {
				add(ls[p],l,mid,x,mid,k);
				add(rs[p],mid+1,r,mid+1,y,k);
			}
	if(!t[p]) c[p]=c[ls[p]]+c[rs[p]];
}
int main() {
int e=0,cnt; db x1,y1,x2,y2; 
while(scanf("%d",&n),n) { 
	printf("Test case #%d\nTotal explored area: ",++e);
	m=0; 
	for(int i=1;i<=n;i++) {
		scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
		a[++m]=(A){x1,y1},id[m]=m;
		a[++m]=(A){x2,y2},id[m]=m; 
	}
	sort(id+1,id+m+1,cmpy);
	cnt=1; fid2[cnt]=a[id[1]].y,a[id[1]].y=cnt;
	for(int i=2;i<=m;i++) {
		if(a[id[i]].y!=fid2[(int)a[id[i-1]].y]) cnt++,fid2[cnt]=a[id[i]].y;
		a[id[i]].y=cnt;
	}
	mx=cnt;
	for(int i=1;i<=m;i++) {
		id[i]=i;
	}
	sort(id+1,id+m+1,cmpx);
	cnt=1; fid1[cnt]=a[id[1]].x,a[id[1]].x=cnt;
	for(int i=2;i<=m;i++) {
		if(a[id[i]].x!=fid1[(int)a[id[i-1]].x]) cnt++,fid1[cnt]=a[id[i]].x;
		a[id[i]].x=cnt;
	}
	for(int i=1;i<=m;i+=2) {
		V[(int)a[i].x].push_back((A){a[i].y,a[i+1].y});
		V1[(int)a[i+1].x].push_back((A){a[i].y,a[i+1].y});
	}
	tot=0,bld(rt);
	db ans=0;
	for(int i=1;i<=cnt;i++) {
		if(i!=1) {
			ans+=c[rt]*(fid1[i]-fid1[i-1]); 
		}
		for(A v:V[i]) {
			if(v.x<v.y) add(rt,1,mx,v.x+1,v.y,1);
		}
		for(A v:V1[i]) {
			if(v.x<v.y) add(rt,1,mx,v.x+1,v.y,-1);
		}
	}
	for(int i=1;i<=m;i++) V[i].clear(),V1[i].clear();
	printf("%.2lf\n",ans);
}
return 0;
}

例题2

C. 【例题3】圆的异或并 - 「计算几何」第5章 扫描线 - 金牌导航 - 课程 - YbtOJ

扫过去,如果是下半部分,则是并列关系,否则被包含

然后可以组成一棵树,深度为奇数的加上为偶数的剪掉

#include<bits/stdc++.h>
#define ll long long
#define db double
using namespace std;

const int N=4e5+5;
int n,m,x[N],y[N],r[N],d[N],now; 
struct A{int x,i,fl; };
struct B{int x,i,fl; }a[N<<1];
inline bool operator <(A i,A j) {
	db y1=(db)i.x+(db)i.fl*sqrt((ll)r[i.i]*r[i.i]-(ll)(x[i.i]-now)*(x[i.i]-now));
	db y2=(db)j.x+(db)j.fl*sqrt((ll)r[j.i]*r[j.i]-(ll)(x[j.i]-now)*(x[j.i]-now));
	return y1<y2||y1==y2&&i.fl<j.fl;
}
set<A>s;

inline bool cmp(B i,B j) {
	return i.x<j.x;
}
ll ans;
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {
		scanf("%d%d%d",&x[i],&y[i],&r[i]);
		a[++m]=(B){x[i]-r[i],i,1},a[++m]=(B){x[i]+r[i],i,-1};
	}
	sort(a+1,a+m+1,cmp);
	for(int i=1;i<=m;i++) {
		now=a[i].x;
		if(a[i].fl==-1) {
			s.erase((A){y[a[i].i],a[i].i,1});
			s.erase((A){y[a[i].i],a[i].i,-1});
		} else {
			auto t=s.upper_bound((A){y[a[i].i],a[i].i,0});
			if(t==s.end()) {
				d[a[i].i]=1;
			} else {
				d[a[i].i]=((t->fl==1)?(!d[t->i]):d[t->i]);
			}
			s.insert((A){y[a[i].i],a[i].i,1});
			s.insert((A){y[a[i].i],a[i].i,-1});
		}
	}
	for(int i=1;i<=n;i++) {
		ans+=d[i]?(ll)r[i]*r[i]:-(ll)r[i]*r[i];
	}
	printf("%lld\n",ans);
}

例题3

D. 矩形周长并 - 「计算几何」第5章 扫描线 - 金牌导航 - 课程 - YbtOJ

维护和面积并一样的线段树

如果加上某条线段后当前的长度增加,则答案加上差值

如果剪掉某条线段后当前的长度减小,则答案也加上差值

#include<bits/stdc++.h>
using namespace std;

const int N=2e4+5;
int n,m,tot,t[N],ls[N],rs[N],id[N],mx,rt,fid1[N],fid2[N],c[N];
struct A{int x,y; }a[N];
vector<A>V[N],V1[N];
inline bool cmpx(int i,int j) {
	return a[i].x<a[j].x;
}
inline bool cmpy(int i,int j) {
	return a[i].y<a[j].y;
}

void bld(int &p) {
	t[p]=c[p]=0;
	if(ls[p]) bld(ls[p]);
	if(rs[p]) bld(rs[p]);
	p=0;
}
void add(int &p,int l,int r,int x,int y,int k) {
	if(x>y) return;
	if(!p) p=++tot;
	if(l==x&&r==y) {
		t[p]+=k;
		if(t[p]) c[p]=fid2[r]-fid2[l-1];
			else c[p]=c[ls[p]]+c[rs[p]];
//	printf("%d %d %d %d %.2lf\n",l,r,x,y,c[p]); 
		return;
	}
	int mid=l+r>>1;
	if(y<=mid) add(ls[p],l,mid,x,y,k);
		else if(x>mid) add(rs[p],mid+1,r,x,y,k);
			else {
				add(ls[p],l,mid,x,mid,k);
				add(rs[p],mid+1,r,mid+1,y,k);
			}
	if(!t[p]) c[p]=c[ls[p]]+c[rs[p]];
//	printf("%d %d %d %d %.2lf\n",l,r,x,y,c[p]); 
}
int main() {
//	freopen("1.in","r",stdin);
while(scanf("%d",&n)!=EOF){
	m=0; 
	for(int i=1;i<=n;i++) {
		int x1,y1,x2,y2; 
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		a[++m]=(A){x1,y1},id[m]=m;
		a[++m]=(A){x2,y2},id[m]=m; 
	}
	sort(id+1,id+m+1,cmpy);
	int cnt2=1; fid2[cnt2]=a[id[1]].y,a[id[1]].y=cnt2;
//	printf("%d %d\n",a[id[3]].y,a[id[4]].y); 
	for(int i=2;i<=m;i++) {
		if(a[id[i]].y!=fid2[a[id[i-1]].y]) cnt2++,fid2[cnt2]=a[id[i]].y;
		a[id[i]].y=cnt2;
	}
/*	for(int i=1;i<=m;i+=2) {
		printf("%d %d %d %d\n",a[i].x,a[i].y,a[i+1].x,a[i+1].y);
	}*/
	for(int i=1;i<=m;i++) {
		id[i]=i;
	}
	sort(id+1,id+m+1,cmpx);
	int cnt1=1; fid1[cnt1]=a[id[1]].x,a[id[1]].x=cnt1;
	for(int i=2;i<=m;i++) {
		if(a[id[i]].x!=fid1[a[id[i-1]].x]) cnt1++,fid1[cnt1]=a[id[i]].x;
		a[id[i]].x=cnt1;
	}
	for(int i=1;i<=m;i+=2) {
		V[a[i].x].push_back((A){a[i].y,a[i+1].y});
		V1[a[i+1].x].push_back((A){a[i].y,a[i+1].y});
	}
	tot=0,bld(rt);
	int ans=0; int lst;
	for(int i=1;i<=cnt1;i++) {
	//	lst=c[rt];
		for(A v:V[i]) {
			if(v.x<v.y) {
				lst=c[rt];
				add(rt,1,cnt2,v.x+1,v.y,1);
				ans+=abs(c[rt]-lst); 
			}
		}
	//	ans+=abs(c[rt]-lst);
	//	lst=c[rt];
		for(A v:V1[i]) {
			if(v.x<v.y) {
				lst=c[rt];
				add(rt,1,cnt2,v.x+1,v.y,-1);
				ans+=abs(c[rt]-lst);
			}
		}
	//	ans+=abs(c[rt]-lst);
	}
//	printf("%d\n",ans);
	for(int i=1;i<=cnt1;i++) V[i].clear(),V1[i].clear();
	swap(cnt1,cnt2);
	for(int i=1;i<=m;i++) {
		swap(fid1[i],fid2[i]);
		swap(a[i].x,a[i].y);
	}
	for(int i=1;i<=m;i+=2) {
		V[a[i].x].push_back((A){a[i].y,a[i+1].y});
		V1[a[i+1].x].push_back((A){a[i].y,a[i+1].y});
	}
	tot=0,bld(rt);
	for(int i=1;i<=cnt1;i++) {
		for(A v:V[i]) {
			if(v.x<v.y) {
				lst=c[rt];
				add(rt,1,cnt2,v.x+1,v.y,1);
				ans+=abs(c[rt]-lst);
			}
		}
		for(A v:V1[i]) {
			if(v.x<v.y) {
				lst=c[rt];
				add(rt,1,cnt2,v.x+1,v.y,-1);
				ans+=abs(c[rt]-lst);
			}
		}
	}
	for(int i=1;i<=cnt1;i++) V[i].clear(),V1[i].clear();
	printf("%d\n",ans);
}
	return 0;
}

例题4

E. 贴海报 - 「计算几何」第5章 扫描线 - 金牌导航 - 课程 - YbtOJ

将其切成4块,求和

#include<bits/stdc++.h>
#define db double
using namespace std;

const int N=4e5+5,M=1e6+5;
int n,m,tot,t[M],ls[M],rs[M],id[N],mx,rt;
db fid1[N],fid2[N],c[M];
struct A{db x,y; }a[N];
vector<A>V[N],V1[N];
inline bool cmpx(int i,int j) {
	return a[i].x<a[j].x;
}
inline bool cmpy(int i,int j) {
	return a[i].y<a[j].y;
}

void bld(int &p) {
	t[p]=c[p]=0;
	if(ls[p]) bld(ls[p]);
	if(rs[p]) bld(rs[p]);
	p=0;
}
void add(int &p,int l,int r,int x,int y,int k) {
	if(x>y) return;
	if(!p) p=++tot;
	if(l==x&&r==y) {
		t[p]+=k;
		if(t[p]) c[p]=fid2[r]-fid2[l-1];
			else c[p]=c[ls[p]]+c[rs[p]];
//	printf("%d %d %d %d %.2lf\n",l,r,x,y,c[p]); 
		return;
	}
	int mid=l+r>>1;
	if(y<=mid) add(ls[p],l,mid,x,y,k);
		else if(x>mid) add(rs[p],mid+1,r,x,y,k);
			else {
				add(ls[p],l,mid,x,mid,k);
				add(rs[p],mid+1,r,mid+1,y,k);
			}
	if(!t[p]) c[p]=c[ls[p]]+c[rs[p]];
//	printf("%d %d %d %d %.2lf\n",l,r,x,y,c[p]); 
}
inline void ins(db x1,db y1,db x2,db y2) {
	if(x1<x2&&y1<y2) {
		a[++m]=(A){x1,y1},id[m]=m;
		a[++m]=(A){x2,y2},id[m]=m;
	}
}
int main() {
//	freopen("1.in","r",stdin);
int cnt; db x1,y1,x2,y2,x3,y3,x4,y4;
while(scanf("%d",&n),n) { 
	m=0; 
	for(int i=1;i<=n;i++) {
		scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
		ins(x1,y1,x3,y2);
		ins(x4,y1,x2,y2);
		ins(x3,y1,x4,y3);
		ins(x3,y4,x4,y2);
	}
	sort(id+1,id+m+1,cmpy);
	cnt=1; fid2[cnt]=a[id[1]].y,a[id[1]].y=cnt;
	for(int i=2;i<=m;i++) {
		if(a[id[i]].y!=fid2[(int)a[id[i-1]].y]) cnt++,fid2[cnt]=a[id[i]].y;
		a[id[i]].y=cnt;
	}
	mx=cnt;
	for(int i=1;i<=m;i++) {
		id[i]=i;
	}
	sort(id+1,id+m+1,cmpx);
	cnt=1; fid1[cnt]=a[id[1]].x,a[id[1]].x=cnt;
	for(int i=2;i<=m;i++) {
		if(a[id[i]].x!=fid1[(int)a[id[i-1]].x]) cnt++,fid1[cnt]=a[id[i]].x;
		a[id[i]].x=cnt;
	}
	for(int i=1;i<=m;i+=2) {
		V[(int)a[i].x].push_back((A){a[i].y,a[i+1].y});
		V1[(int)a[i+1].x].push_back((A){a[i].y,a[i+1].y});
	}
	tot=0,bld(rt);
	db ans=0;
	for(int i=1;i<=cnt;i++) {
		if(i!=1) {
			ans+=c[rt]*(fid1[i]-fid1[i-1]); 
		}
		for(A v:V[i]) {
			if(v.x<v.y) add(rt,1,mx,v.x+1,v.y,1);
		}
		for(A v:V1[i]) {
			if(v.x<v.y) add(rt,1,mx,v.x+1,v.y,-1);
		}
	}
	for(int i=1;i<=m;i++) V[i].clear(),V1[i].clear();
	printf("%.0lf\n",ans);
}
return 0;
}

例题5

F. 三角形面积并 - 「计算几何」第5章 扫描线 - 金牌导航 - 课程 - YbtOJ

将交点和顶点切开,则都是一大堆梯形,边和边只存在包含关系

#include <bits/stdc++.h>
#define db long double
const db eps = 1e-9, INF = 1e6;
using namespace std;

const int N = 106, M = 1005;
int n;
struct Po {
    db x, y;
} a[N], b[N], c[N];
struct Li {
    Po s, t;
};
inline Po operator-(Po i, Po j) { return (Po){ i.x - j.x, i.y - j.y }; }
inline Po operator*(Po i, db j) { return (Po){ i.x * j, i.y * j }; }
inline Po operator+(Po i, Po j) { return (Po){ i.x + j.x, i.y + j.y }; }
inline db operator*(Po i, Po j) { return i.x * j.y - i.y * j.x; }
inline bool equ(db x, db y) { return abs(x - y) <= eps; }
inline bool XX(Li x, Li y) {
    Po A = x.s, B = x.t, C = y.s, D = y.t;
    return ((C - A) * (D - A)) * ((C - B) * (D - B)) <= eps &&
           ((A - C) * (B - C)) * ((A - D) * (B - D)) <= eps;
}
inline Po Crs(Li x, Li y) {
    Po A = x.s, B = x.t, C = y.s, D = y.t;
    db s1 = abs((C - A) * (D - A)), s2 = abs((C - B) * (D - B));
    return A + (B - A) * (s1 / (s1 + s2));
}
set<db> s;
void ins(Li x, Li y) {
    if (XX(x, y) && !equ(0, (x.s - x.t) * (y.s - y.t))) {
        Po t = Crs(x, y);
        s.insert(t.x);
    }
}
inline bool cmp(Po i, Po j) { return i.x < j.x; }
vector<Po> V;
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%Lf%Lf", &a[i].x, &a[i].y);
        scanf("%Lf%Lf", &b[i].x, &b[i].y);
        scanf("%Lf%Lf", &c[i].x, &c[i].y);
        if (a[i].x > c[i].x)
            swap(a[i], c[i]);
        if (a[i].x > b[i].x)
            swap(a[i], b[i]);
        if (b[i].x > c[i].x)
            swap(b[i], c[i]);
        s.insert(a[i].x);
        s.insert(b[i].x);
        s.insert(c[i].x);
    }
    for (int i = 1; i < n; i++) {
        Li l1 = (Li){ a[i], b[i] }, l2 = (Li){ a[i], c[i] }, l3 = (Li){ b[i], c[i] };
        for (int j = i + 1; j <= n; j++) {
            Li l4 = (Li){ a[j], b[j] }, l5 = (Li){ a[j], c[j] }, l6 = (Li){ b[j], c[j] };
            ins(l1, l4), ins(l1, l5), ins(l1, l6);
            ins(l2, l4), ins(l2, l5), ins(l2, l6);
            ins(l3, l4), ins(l3, l5), ins(l3, l6);
        }
    }
    db sum = 0, ans = 0, lst = 0;
    for (db j : s) {
        ans += (j - lst) * sum * 0.5;
        Li l = (Li){ (Po){ j, -INF }, (Po){ j, INF } };
        V.clear();
        for (int i = 1; i <= n; i++) {
            if (a[i].x <= j && j <= c[i].x) {
                Po t1 = Crs(l, (Li){ a[i], c[i] }), t2;
                if (t1.x <= b[i].x && !equ(a[i].x, b[i].x)) {
                    t2 = Crs(l, (Li){ a[i], b[i] });
                } else {
                    t2 = Crs(l, (Li){ b[i], c[i] });
                }
                db l = t1.y, r = t2.y;
                if (l > r)
                    swap(l, r);
                V.push_back((Po){ l, 1 });
                V.push_back((Po){ r, -1 });
            }
        }
        sort(V.begin(), V.end(), cmp);
        sum = 0;
        int res = 0;
        db Lst;
        for (auto i : V) {
            if (i.y == 1) {
                if (res == 0)
                    Lst = i.x;
                res++;
            } else {
                res--;
                if (res == 0)
                    sum += i.x - Lst;
            }
        }
        if (j != *s.begin())
            ans += sum * (j - lst) * 0.5;
        lst = j;
    }
    printf("%.2Lf\n", ans-eps);
    return 0;
}

例题6

G. 布娃娃 - 「计算几何」第5章 扫描线 - 金牌导航 - 课程 - YbtOJ

每次区间加,单点求第K大,扫描线+权值线段树

#include<bits/stdc++.h>
#define ll long long
const int p=19921228;
using namespace std;

const int N=1e5+5,M=6e6+5;
int n,a[N],b[N],L[N],R[N],mx,c[M],fid[N];
struct A{int x,y,fl; };
vector<A>V;
inline void Get(int *f) {
	int Padd,Pfirst,Pmod,Pprod;
	scanf("%d%d%d%d",&Padd,&Pfirst,&Pmod,&Pprod);
	f[1]=Pfirst%Pmod;
	for(int i=2; i<=n; i++)
		f[i]=((ll)f[i-1]*Pprod+Padd+i)%Pmod;
	
}
inline bool cmp(A i,A j) {
	return i.x<j.x||i.x==j.x&&i.fl<j.fl;
}

void add(int p,int l,int r,int x,int k) {
	c[p]+=k;
	if(l==r) return;
	int mid=l+r>>1;
	if(x<=mid) add(p<<1,l,mid,x,k);
		else add(p<<1|1,mid+1,r,x,k);
}

int kth(int p,int l,int r,int k) {
	if(l==r) return l;
	int mid=l+r>>1,d=c[p<<1|1];
	if(d>=k) return kth(p<<1|1,mid+1,r,k);
	return kth(p<<1,l,mid,k-d);
}
int main() {
	scanf("%d",&n);
	Get(a),Get(b),Get(L),Get(R);
	for(int i=1;i<=n;i++) fid[i]=b[i];
	sort(fid+1,fid+n+1);
	for(int i=1;i<=n;i++) b[i]=lower_bound(fid+1,fid+n+1,b[i])-fid;
	for(int i=1;i<=n;i++) {
		if(L[i]>R[i]) swap(L[i],R[i]);
		V.push_back((A){L[i],b[i],1});
		V.push_back((A){R[i]+1,b[i],-1});
		V.push_back((A){a[i],i,2});
	}
	sort(V.begin(),V.end(),cmp);
	int ans=0;
	for(A v:V) {
		if(v.fl==2) {
			if(c[1]>=v.y) {
				ans=(ans+fid[kth(1,1,n,v.y)])%p
			}
		} else {
			add(1,1,n,v.y,v.fl);
		}
	}
	printf("%d\n",ans);
	return 0;
}

例题7

H. 立方体覆盖 - 「计算几何」第5章 扫描线 - 金牌导航 - 课程 - YbtOJ

多了一维,多枚举1维

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int N=205,M=805;
int n,m,tot,t[M],ls[M],rs[M],rt,fid1[N],mx1,mx2,mx3,fid2[N],fid3[N],c[M];
struct A{int x,y,z; }a[N];
struct B{int x1,y1,x2,y2,fl; };
vector<B>V1[N];
struct C{int x,y,fl; };

void bld(int &p) {
	t[p]=c[p]=0;
	if(ls[p]) bld(ls[p]);
	if(rs[p]) bld(rs[p]);
	p=0;
}
void add(int &p,int l,int r,int x,int y,int k) {
	if(!p) p=++tot;
	if(l==x&&r==y) {
		t[p]+=k;
		if(t[p]) c[p]=fid3[r]-fid3[l-1];
			else c[p]=c[ls[p]]+c[rs[p]];
		return;
	}
	int mid=l+r>>1;
	if(y<=mid) add(ls[p],l,mid,x,y,k);
		else if(x>mid) add(rs[p],mid+1,r,x,y,k);
			else {
				add(ls[p],l,mid,x,mid,k);
				add(rs[p],mid+1,r,mid+1,y,k);
			}
	if(!t[p]) c[p]=c[ls[p]]+c[rs[p]];
}
inline bool operator <(C i,C j) {
	return i.x<j.x||i.x==j.x&&i.y<j.y||i.x==j.x&&i.y==j.y&&i.fl<j.fl;
}
set<C>V2[N];
int main() {
	scanf("%d",&n);
	m=0; 
	for(int i=1;i<=n;i++) {
		int x,y,z,r;
		scanf("%d%d%d%d",&x,&y,&z,&r);
		a[++m]=(A){x-r,y-r,z-r},fid1[m]=x-r,fid2[m]=y-r,fid3[m]=z-r;
		a[++m]=(A){x+r,y+r,z+r},fid1[m]=x+r,fid2[m]=y+r,fid3[m]=z+r;
	}	
	sort(fid1+1,fid1+m+1);
	mx1=unique(fid1+1,fid1+m+1)-fid1-1;
	for(int i=1;i<=m;i++) {
		a[i].x=lower_bound(fid1+1,fid1+mx1+1,a[i].x)-fid1;
	}
	sort(fid2+1,fid2+m+1);
	mx2=unique(fid2+1,fid2+m+1)-fid2-1;
	for(int i=1;i<=m;i++) {
		a[i].y=lower_bound(fid2+1,fid2+mx2+1,a[i].y)-fid2;
	}
	sort(fid3+1,fid3+m+1);
	mx3=unique(fid3+1,fid3+m+1)-fid3-1;
	for(int i=1;i<=m;i++) {
		a[i].z=lower_bound(fid3+1,fid3+mx3+1,a[i].z)-fid3;
	}
	for(int i=1;i<=m;i+=2) {
		V1[a[i].x].push_back((B){a[i].y,a[i].z,a[i+1].y,a[i+1].z,1});
		V1[a[i+1].x].push_back((B){a[i].y,a[i].z,a[i+1].y,a[i+1].z,-1}); 
	}
	ll ans=0,sum=0;
	for(int i=1;i<mx1;i++) {
		for(B j:V1[i]) {
			if(j.fl==-1) {
				V2[j.x1].erase((C){j.y1,j.y2,1});
				V2[j.x2].erase((C){j.y1,j.y2,-1});
			} else {
				V2[j.x1].insert((C){j.y1,j.y2,1});
				V2[j.x2].insert((C){j.y1,j.y2,-1});
			}
		}
		bld(rt),tot=0;
		sum=0;
		for(int j=1;j<=mx2;j++) {
			for(C k:V2[j]) {
				if(k.x<k.y) add(rt,1,mx3,k.x+1,k.y,k.fl);
			}
			if(j<mx2) sum+=(ll)(fid2[j+1]-fid2[j])*c[rt];
		}
		ans+=(ll)(fid1[i+1]-fid1[i])*sum;
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2021-04-27 11:10  wwwsfff  阅读(71)  评论(0编辑  收藏  举报