线段树维护扫描线

你需要实现一种数据结构支持以下操作:

  1. 区间加减 1
    保证加减区间一一对应,且先加后减,序列中永远不出现负数。
  2. 查询完整序列中 0 的个数
#include <cstdio>
#include <algorithm>

const int maxn = 1e5 + 10;

long long x[maxn * 2];

struct segmentTree
{
	struct node
	{
		int l, r;
		long long min, len, tag;
	}
	T[maxn * 2 * 4];
	
	void downdata(int p)
	{
		T[p << 1].min += T[p].tag, T[p << 1].tag += T[p].tag;
		T[(p << 1) | 1].min += T[p].tag, T[(p << 1) | 1].tag += T[p].tag;
		T[p].tag = 0;
	}
	
	void updata(int p)
	{
		T[p].min = std::min(T[p << 1].min, T[(p << 1) | 1].min);
		T[p].len = T[p << 1].len * (T[p << 1].min == T[p].min) + T[(p << 1) | 1].len * (T[(p << 1) | 1].min == T[p].min);
	}
	
	void build(int p, int l, int r)
	{
		T[p].l = l, T[p].r = r, T[p].tag = 0, T[p].min = 0, T[p].len = x[r + 1] - x[l];
		if (l != r) build(p << 1, l, (l + r) >> 1), build((p << 1) | 1, ((l + r) >> 1) + 1, r), updata(p);
	}
	
	void add(int p, int l, int r, long long k)
	{
		if (r < T[p].l || T[p].r < l) return;
		else if (l <= T[p].l && T[p].r <= r) T[p].tag += k, T[p].min += k;
		else downdata(p), add(p << 1, l, r, k), add((p << 1) | 1, l, r, k), updata(p);
	}
	
	long long query(int p, int l, int r)
	{
		if (r < T[p].l || T[p].r < l) return 0;
		else if (l <= T[p].l && T[p].r <= r) return T[p].min == 0 ? T[p].len : 0;
		else return downdata(p), query(p << 1, l, r) + query((p << 1) | 1, l, r);
	}
}
T;

struct node
{
	long long x1, x2, y, k;
	bool operator < (const node &that) const { return (*this).y < that.y; }
	node(long long _x1 = 0, long long _x2 = 0, long long _y = 0, long long _k = 0) { x1 = _x1, x2 = _x2, y = _y, k = _k; }
}
a[maxn * 2];

int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		long long x1, y1, x2, y2;
		scanf("%lld %lld %lld %lld", &x1, &y1, &x2, &y2);
		a[2 * i - 1] = {x1, x2, y1, 1}, a[2 * i] = {x1, x2, y2, -1};
		x[2 * i - 1] = x1, x[2 * i] = x2;
	}
	std::sort(a + 1, a + 2 * n + 1);
	std::sort(x + 1, x + 2 * n + 1);
	int len = std::unique(x + 1, x + 2 * n + 1) - (x + 1);
	T.build(1, 1, len - 1);
	long long ans = 0;
	for (int i = 1; i <= 2 * n - 1; i++)
	{
		T.add(1, std::lower_bound(x + 1, x + len + 1, a[i].x1) - x, std::lower_bound(x + 1, x + len + 1, a[i].x2) - x - 1, a[i].k);
		ans += (a[i + 1].y - a[i].y) * (x[len] - x[1] - T.query(1, 1, len - 1));
	}
	printf("%lld", ans);
	return 0;
}
posted @ 2024-01-16 23:45  wxir  阅读(37)  评论(4)    收藏  举报