四维偏序 | CDQ 的嵌套

从常规的三维偏序扩展为四维偏序。

同样地,我们先按第一维 \(a\) 排序。

我们对第二维 \(b\) CDQ 分治,记 \(\operatorname{cdqB}(l,r)\) 表示处理所有 \([l,r]\) 之间的偏序转移关系,记 \(\text{mid}=\dfrac{l+r}{2}\)

同样地,我们递归 \(\operatorname{cdqB}(l,\text{mid})\)\(\operatorname{cdqB}(\text{mid}+1,r)\),再两次递归中间处理跨越 \(\text{mid}\) 的转移。

我们把 \([l,\text{mid}]\) 中的元素打上黑色标记,把 \([\text{mid}+1,r]\) 中的元素打上白色标记,把 \([l,r]\) 中的元素按照第三维 \(c\) 排序。

我们再对 \(c\) CDQ,记 \(\operatorname{cdqC}(l,r)\) 表示处理所有 \([l,r]\) 之间 \(c,d\) 的偏序转移关系,这就是普通的三维偏序了。

我们只需要考虑所有黑色点对白色点的贡献。可以把黑色点看做修改操作,白色点为询问操作。

  • 时间复杂度 \(\mathcal{O}(n\log^3n)\)

同样可以把其扩展到 \(k\) 维偏序,时间复杂度 \(\mathcal{O}(n\log^{k-1}n)\)

注意,stable_sort

代码

#include <bits/stdc++.h>
#define sort stable_sort
using namespace std;
#define int long long
#define pii pair<int, int> 
#define fi first
#define se second 
#define mp make_pair
int n, f[200010];
int len, lsh[200010];
struct Node {
	int id, bp, a, b, c, d, w;
} a[50010], b[50010], c[50010]; 
bool cmpD(Node a, Node b) { return a.d < b.d; }
bool cmpC(Node a, Node b) {
	if (a.c != b.c) return a.c < b.c; else return cmpD(a, b);
}
bool cmpB(Node a, Node b) {
	if (a.b != b.b) return a.b < b.b; else return cmpC(a, b);
}
bool cmpA(Node a, Node b) {
	if (a.a != b.a) return a.a < b.a; else return cmpB(a, b);
}
struct Bit {
	int w[200010];
	void add(int p, int x) {
		for (int i = p; i <= len; i += i & (-i)) w[i] = max(w[i], x);
	}
	void put(int p) {
		for (int i = p; i <= len; i += i & (-i)) w[i] = 0;
	}
	int query(int p) {
		int res = 0;
		for (int i = p; i; i -= i & (-i)) res = max(res, w[i]);
		return res;
	}
} bit;
void cdqC(int l, int r, Node *a) {
	if (l == r) return;
	int mid = (l + r) >> 1;
	cdqC(l, mid, a);
	for (int i = l; i <= r; i++) c[i] = a[i];
	sort(c + l, c + mid + 1, cmpC); sort(c + mid + 1, c + r + 1, cmpC);
	int lp = l - 1;
	for (int i = mid + 1; i <= r; i++) {
		while (lp < mid && c[lp + 1].c <= c[i].c) {
			lp++;
			if (c[lp].bp) bit.add(c[lp].d, f[c[lp].id]);
		}
		if (c[i].bp == 0) f[c[i].id] = max(f[c[i].id], bit.query(c[i].d));
	}
	lp = l - 1;
	for (int i = mid + 1; i <= r; i++) {
		while (lp < mid && c[lp + 1].c <= c[i].c) {
			lp++;
			bit.put(c[lp].d);
		}
	}
	cdqC(mid + 1, r, a);
}
void cdqB(int l, int r) {
	if (l == r) {
		f[a[l].id] += a[l].w;
		return;
	}
	int mid = (l + r) >> 1;
	cdqB(l, mid);
	for (int i = l; i <= mid; i++) a[i].bp = 1;
	for (int i = mid + 1; i <= r; i++) a[i].bp = 0;
	for (int i = l; i <= r; i++) b[i] = a[i];
	sort(b + l, b + r + 1, cmpB); cdqC(l, r, b);
	cdqB(mid + 1, r);
}
void plsh(int x) { lsh[++len] = x; }
void lb(int &x) { x = lower_bound(lsh + 1, lsh + len + 1, x) - lsh; }
signed main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		a[i].id = i;
		cin >> a[i].a >> a[i].b >> a[i].c >> a[i].d >> a[i].w;
		plsh(a[i].a), plsh(a[i].b), plsh(a[i].c), plsh(a[i].d);
	}
	sort(lsh + 1, lsh + len + 1); 
	len = unique(lsh + 1, lsh + len + 1) - lsh - 1;
	for (int i = 1; i <= n; i++) lb(a[i].a), lb(a[i].b), lb(a[i].c), lb(a[i].d);
	sort(a + 1, a + n + 1, cmpA);
	cdqB(1, n);
	int ans = 0;
	for (int i = 1; i <= n; i++) ans = max(ans, f[i]);
	cout << ans << endl;
	return 0;
} 
posted @ 2022-12-17 20:56  Network_Error  阅读(251)  评论(0)    收藏  举报