矩形面积并

矩形面积并

扫描线,线段树

http://oj.daimayuan.top/course/15/problem/688

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <array>
using namespace std;
#define endl "\n"

typedef long long ll;
typedef pair<int, int> PII;

const int N = 2e5 + 10;
int n, m;

vector<int> vx;
vector<array<int, 4> > event;

struct info
{
	int minv, mincnt;
};

info operator + (const info &l, const info &r)
{
	info t;
	t.minv = min(l.minv, r.minv);
	if (l.minv == r.minv)
		t.mincnt = l.mincnt + r.mincnt;
	else if (l.minv < r.minv)
		t.mincnt = l.mincnt;
	else
		t.mincnt = r.mincnt;
	return t;
}

struct Node
{
	int t;
	info val;
}seg[N * 8];

void pushup(int u)
{
	seg[u].val = seg[u << 1].val + seg[u << 1 | 1].val;
}

void settag(int u, int t)
{
	seg[u].val.minv += t;
	seg[u].t += t;
}

void pushdown(int u)
{
	if (seg[u].t)
	{
		settag(u << 1, seg[u].t);
		settag(u << 1 | 1, seg[u].t);
		seg[u].t = 0;
	}
}

void build(int u, int l, int r)
{
	if (l == r)
	{
		//以段而不是点建线段树
		seg[u].val = {0, vx[r] - vx[r-1]};
		return;
	}
	int mid = l + r >> 1;
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
	pushup(u);
}

void modify(int u, int l, int r, int ql, int qr, int k)
{
	if (l == ql && r == qr)
	{
		settag(u, k);
		return;
	}
	int mid = l + r >> 1;
	pushdown(u);
	if (qr <= mid)
		modify(u << 1, l, mid, ql, qr, k);
	else if (ql > mid)
		modify(u << 1 | 1, mid + 1, r, ql, qr, k);
	else
	{
		modify(u << 1, l, mid, ql, mid, k);
		modify(u << 1 | 1, mid + 1, r, mid + 1, qr, k);
	}
	pushup(u);
}


int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		int x1, x2, y1, y2;
		scanf("%d%d%d%d", &x1, &x2, &y1, &y2);
		vx.push_back(x1);
		vx.push_back(x2);
		event.push_back({y1, 1, x1, x2});
		event.push_back({y2, -1, x1, x2});
	}
	sort(event.begin(), event.end());
	sort(vx.begin(), vx.end());
	vx.erase(unique(vx.begin(), vx.end()), vx.end());
	
	m = vx.size() - 1;
	build(1, 1, m);
	int totlen = seg[1].val.mincnt;
	int prey = 0;
	ll ans = 0;
	for (auto evt : event)
	{
		int cov = totlen;
		if (seg[1].val.minv == 0)
			cov = totlen - seg[1].val.mincnt;
		ans += (ll)(evt[0] - prey) * cov;
		prey = evt[0];
		int x1 = lower_bound(vx.begin(), vx.end(), evt[2]) - vx.begin() + 1;
		int x2 = lower_bound(vx.begin(), vx.end(), evt[3]) - vx.begin();
		if (x1 > x2)
			continue;
		modify(1, 1, m, x1, x2, evt[1]);
	}
	printf("%lld\n", ans);
    return 0;
}
posted @ 2022-06-07 15:15  hzy0227  阅读(21)  评论(0编辑  收藏  举报