扫描线

#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define mkp make_pair
#define pb push_back
#define mid ((l+r)>>1)
#define ls(x) (x<<1)
#define rs(x) ((x<<1)+1)
#define LL long long
#define int long long

const int maxn = 1e6 + 10;

int read() {
	int flag = 1, res = 0;
	char c = getchar();
	while (c < '0' || c>'9')
	{
		if (c == '-')flag = -1; c = getchar();
	}
	while (c >= '0' && c <= '9')
		res = res * 10 + c - '0',c=getchar();
	return res * flag;
}

struct Node {
	int w;int len;
}t[maxn*4];
struct Level {
	int xs, xt, ys,w;
}lev[maxn*2];
int X[maxn*2];

bool cmp(const Level & x, const Level & y) {
	if (x.ys == y.ys)return x.w < y.w;
	return x.ys < y.ys;
}
void push_up(int x,int l,int r) {
	t[x].len = t[ls(x)].len + t[rs(x)].len;
	if (t[x].w)t[x].len = X[r + 1] - X[l];
}
void upd(int x, LL ql,LL qr, int l, int r, int k) {
	//总结点数改为tot-1然后查询r+1直接避免了l==r(查点)的情况
	if (X[r + 1] <= ql || X[l] >= qr)return;
	//这边return相等也是因为不查点
	if (ql <= X[l] && qr >= X[r + 1]) {
		t[x].w += k;
		push_up(x, l, r);//为了维护x的len值而pushup**
		return;
	}
	//非传统线段树判递归
	upd(ls(x), ql, qr, l, mid, k);
	upd(rs(x), ql, qr, mid + 1, r, k);
	push_up(x,l,r);
}
signed main() {
	int n = read();
	for (int i = 1; i <= n; i++) {
		int x0 = read(), y0 = read(), x2 = read(), y2 = read();
		X[2 * i - 1] = x0; X[2 * i] = x2;
		lev[2 * i - 1] =  { x0,x2,y0,1 };
		lev[2 * i ] =  { x0,x2,y2,-1 };
	}
	n *= 2;
	sort(lev + 1, lev + n + 1, cmp);
	sort(X + 1, X + n + 1);
	int tot = unique(X + 1, X + n + 1) - X - 1;
	LL ans = 0;
	for (int i = 1; i < n; i++) {
		upd(1, lev[i].xs, lev[i].xt,1,tot-1, lev[i].w);
		ans += t[1].len * (lev[i + 1].ys - lev[i].ys);
	}
	cout << ans << endl;
}
posted @ 2024-09-11 18:28  lyrrr  阅读(14)  评论(0)    收藏  举报