如何使用 SATT 水掉 Qtree 系列题(详细揭秘)

UPD:部分代码已添加注释(原先一个注释都没有)

这是为了方便大家学习如何实现 SATT 而写的一篇文章。

前几个 QTree 题没用 SATT 写。

Qtree 1

Code(树剖)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Edge {
	int t, n, w, id;
} e[200005];
int n, tot, h[100005];
void InsEdge(int u, int v, int w, int id) { e[++tot] = {v, h[u], w, id}, h[u] = tot; }
int p[100005];
int siz[100005], dep[100005], fa[100005], val[100005], son[100005];
void DFS1(int u, int fth) {
	siz[u] = 1, dep[u] = dep[fa[u] = fth] + 1;
	for (int i = h[u]; i; i = e[i].n) {
		int v = e[i].t;
		if (v != fth) {
			val[p[e[i].id] = v] = e[i].w;
			DFS1(v, u), siz[u] += siz[v];
			if (siz[v] > siz[son[u]]) son[u] = v;
		}
	}
}
int top[100005], dfn[100005], id[100005];
void DFS2(int u, int tp) {
	top[id[dfn[u] = ++*dfn] = u] = tp;
	if (son[u]) DFS2(son[u], tp);
	for (int i = h[u]; i; i = e[i].n) {
		int v = e[i].t;
		if (v != son[u] && v != fa[u]) DFS2(v, v);
	}
}
#define ls (u << 1)
#define rs ((u << 1) | 1)
#define mid ((l + r) >> 1)
int mx[400005];
void Up(int u) { mx[u] = max(mx[ls], mx[rs]); }
void Build(int u, int l, int r) {
	if (l == r) return mx[u] = val[id[l]], void();
	Build(ls, l, mid), Build(rs, mid + 1, r), Up(u);
}
void Upd(int u, int l, int r, int x, int v) {
	if (x < l || r < x) return;
	if (l == r) return mx[u] = v, void();
	Upd(ls, l, mid, x, v), Upd(rs, mid + 1, r, x, v), Up(u);
}
int Qry(int u, int l, int r, int x, int y) {
	if (y < l || r < x || x > y) return 0;
	if (x <= l && r <= y) return mx[u];
	return max(Qry(ls, l, mid, x, y), Qry(rs, mid + 1, r, x, y));
}
#undef ls
#undef rs
#undef mid
int main() {
	scanf("%d", &n);
	for (int i = 1, u, v, w; i < n; ++i) {
		scanf("%d%d%d", &u, &v, &w), InsEdge(u, v, w, i), InsEdge(v, u, w, i);
	}
	DFS1(1, 0), DFS2(1, 1), Build(1, 1, n);
	while (true) {
		char str[999];
		scanf(" %s", str);
		if (str[0] == 'C') {
			int x, t;
			scanf("%d%d", &x, &t);
			int u = p[x];
			Upd(1, 1, n, dfn[u], t);
		}
		else if (str[0] == 'Q') {
			int u, v;
			scanf("%d%d", &u, &v);
			int ans = 0;
			while (top[u] != top[v]) {
				if (dep[top[u]] < dep[top[v]]) swap(u, v);
				ans = max(ans, Qry(1, 1, n, dfn[top[u]], dfn[u]));
				u = fa[top[u]];
			}
			if (dep[u] > dep[v]) swap(u, v);
			ans = max(ans, Qry(1, 1, n, dfn[u] + 1, dfn[v]));
			printf("%d\n", ans);
		}
		else {
			break;
		}
	}
	return 0;
}

Qtree 2

Code (倍增)
#include <bits/stdc++.h>

using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;

void solve() {
	int n;
	std::cin >> n;
	std::vector<std::vector<std::pair<int, int>>> e(n, std::vector<std::pair<int, int>>());
	for (int i = 1; i < n; ++i) {
		int u, v, w;
		std::cin >> u >> v >> w;
		--u, --v;
		e[u].push_back({v, w}), e[v].push_back({u, w});
	}

	int ln = std::__lg(n);
	std::vector<int> dep(n), dis(n), fa(n);
	std::vector<std::vector<int>> kfa(ln + 1, std::vector<int>(n));
	std::function<void(int, int)> dfs = [&](int u, int fth) {
		fa[u] = kfa[0][u] = fth;
		for (auto [v, w] : e[u]) {
			if (v == fth) continue;
			dep[v] = dep[u] + 1;
			dis[v] = dis[u] + w;
			dfs(v, u);
		}
	};
	dfs(0, -1);
	for (int j = 1; j <= ln; ++j)
		for (int i = 0; i < n; ++i)
			kfa[j][i] = kfa[j - 1][kfa[j - 1][i]];
	
	auto kthanc = [&](int u, int k) {
		for (int i = 0; i <= ln; ++i) {
			if ((k >> i) & 1) u = kfa[i][u];
		}
		return u;
	};
	auto LCA = [&](int u, int v) {
		if (dep[u] < dep[v]) std::swap(u, v);
		u = kthanc(u, dep[u] - dep[v]);
		if (u == v) return u;
		for (int i = ln; i >= 0; --i) {
			if (kfa[i][u] != kfa[i][v]) u = kfa[i][u], v = kfa[i][v];
		}
		return fa[u];
	};
	
	while (true) {
		std::string str;
		std::cin >> str;
		if (str[1] == 'I') {
			int u, v;
			std::cin >> u >> v;
			--u, --v;
			std::cout << dis[u] + dis[v] - 2 * dis[LCA(u, v)] << '\n';
		} else if (str[1] == 'T') {
			int u, v, k;
			std::cin >> u >> v >> k;
			--u, --v;
			int lca = LCA(u, v);
			int L = dep[u] - dep[lca], R = dep[v] - dep[lca];
			if (k <= L) {
				std::cout << kthanc(u, k - 1) + 1 << '\n';
			} else {
				std::cout << kthanc(v, L + R - k + 1) + 1 << '\n';
			}
		} else break;
	}
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);

	int t = 1;
	std::cin >> t;
	while (t--) {
		solve();
	}

	return 0;
}

Qtree 3

Code (LCT)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int> G[100005];
int n, q;
int ans[100005], ch[100005][2], fa[100005], col[100005];
#define get(u) (u == ch[fa[u]][1])
#define nrt(u) (u == ch[fa[u]][0] || u == ch[fa[u]][1])
void up(int u) {
	ans[u] = col[u] ? u : -1;
	if (ch[u][0] && ans[ch[u][0]] != -1) ans[u] = ans[ch[u][0]];
	if (ch[u][1] && ans[u] == -1 && ans[ch[u][1]] != -1) ans[u] = ans[ch[u][1]];
}
void rot(int u) {
	int f = fa[u], g = fa[f], k = get(u);
	if (nrt(f)) ch[g][get(f)] = u;
	fa[u] = g, ch[f][k] = ch[u][!k];
	if (ch[u][!k]) fa[ch[u][!k]] = f;
	ch[u][!k] = f, fa[f] = u, up(f), up(u);
}
void spl(int u) { for (; nrt(u); rot(u)) if (nrt(fa[u])) rot(get(fa[u]) == get(u) ? fa[u] : u); }
void acc(int u) { for (int v = 0; u; v = u, u = fa[u]) spl(u), ch[u][1] = v, up(u); }
void DFS(int u, int f) {
	fa[u] = f;
	for (int v : G[u]) if (v != f) DFS(v, u);
}
int main() {
	scanf("%d%d", &n, &q);
	for (int i = 1, u, v; i < n; ++i) scanf("%d%d", &u, &v), G[u].push_back(v), G[v].push_back(u), up(u);
	DFS(1, 0);
	while (q--) {
		int op, u;
		scanf("%d%d", &op, &u);
		if (op == 0) acc(u), spl(u), col[u] ^= 1, up(u);
		else acc(u), spl(u), printf("%d\n", ans[u]);
	}
	return 0;
}

Qtree 4

这题我有两种 push_up 写法,这是更通用的一种

就是专门写了 Rake(x, y)Compress(u, l, r) 两个函数来方便地处理信息合并

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 1e9;
struct Node {
	int fa, ch[3], lef, rig;
	// lef: u 所在树的最左节点
	// rig: u 所在树的最右节点
	int col, val;
	// col: 1 表示白色,0 表示黑色,2 表示这个点是边
	int len, dis[2], ans;
	// len: 簇路径长度
	// dis[0/1]: 上/下界点的答案
	// ans: 这个簇的答案
	bool rev;
	// rev: 翻转标记
	Node() {
		fa = ch[0] = ch[1] = ch[2] = lef = rig = col = val = len = 0;
		dis[0] = dis[1] = ans = -inf, rev = false;
	}
	void Clear() { *this = Node(); }
} f[1000005];
int cnt, tp, st[1000005];
#define ls(x) f[x].ch[0]
#define ms(x) f[x].ch[2]
#define rs(x) f[x].ch[1]
#define fa(x) f[x].fa
#define lef(x) f[x].lef
#define rig(x) f[x].rig
void Clear(int x) { f[st[++tp] = x].Clear(); }
int NewNode() { return tp ? st[tp--] : ++cnt; }
int Get(int x) { return ls(fa(x)) == x ? 0 : (rs(fa(x)) == x ? 1 : 2); }
bool Nrt(int x) { return ls(fa(x)) == x || rs(fa(x)) == x; }
void Set(int x, int y, int t) { if (x) f[fa(x)].ch[Get(x)] = 0, fa(x) = y; f[y].ch[t] = x; }
void Cpy(int x, int y) { f[x].len = f[y].len, f[x].dis[0] = f[y].dis[0], f[x].dis[1] = f[y].dis[1], f[x].ans = f[y].ans; }
void Rev(int x, bool t = true) {
	swap(ls(x), rs(x)), swap(lef(x), rig(x)), swap(f[x].dis[0], f[x].dis[1]), f[x].rev ^= 1;
	if (t && f[x].rev) Rev(ls(x), false), Rev(rs(x), false), f[x].rev = false;
}
void down(int x, int t) { if (!t && f[x].rev) Rev(ls(x)), Rev(rs(x)), f[x].rev = false; }
void Down(int x, int t) { if (Nrt(x)) Down(fa(x), t); down(x, t); }
void Rake(int x, int y) {
	f[x].ans = max({ f[x].ans, f[y].ans, f[x].dis[0] + f[y].dis[0] });
	f[x].dis[0] = max(f[x].dis[0], f[y].dis[0]);
	f[x].dis[1] = max(f[x].dis[1], f[x].len + f[y].dis[0]);
}
void Compress(int x, int l, int r) {
	auto L = f[l], R = f[r];
	f[x].len = L.len + R.len;
	f[x].dis[0] = max(L.dis[0], L.len + R.dis[0]);
	f[x].dis[1] = max(R.dis[1], R.len + L.dis[1]);
	f[x].ans = max({ L.ans, R.ans, L.dis[1] + R.dis[0] });
}
void Up(int x, int t) {
	lef(x) = ls(x) ? lef(ls(x)) : x, rig(x) = rs(x) ? rig(rs(x)) : x;
	if (!t) {
		f[x].len = f[x].val;
		if (f[x].col == 1) {
			f[x].dis[0] = f[x].dis[1] = f[x].ans = 0;
		} else {
			f[x].dis[0] = f[x].dis[1] = f[x].ans = -inf;
		}
		Rake(x, ms(x));
		Compress(x, ls(x), x);
		Compress(x, x, rs(x));
	} else {
		Cpy(x, ms(x));
		Rake(x, ls(x));
		Rake(x, rs(x));
	}
}
void Rot(int x, int t) {
	int y = fa(x), z = fa(y), d = Get(x), p = f[x].ch[!d];
	if (z) f[z].ch[Get(y)] = x;
	if (p) fa(p) = y;
	fa(x) = z, f[x].ch[!d] = y, fa(y) = x, f[y].ch[d] = p, Up(y, t), Up(x, t);
}
void Splay(int x, int t, int tar = 0) {
	for (Down(x, t); Nrt(x) && fa(x) != tar; Rot(x, t))
		if (Nrt(fa(x)) && fa(fa(x)) != tar) Rot(Get(x) == Get(fa(x)) ? fa(x) : x, t);
}
void Del(int x) { // R
	if (ls(x)) {
		int y = f[ls(x)].rig;
		Splay(y, 1, x), Set(rs(x), y, 1), Set(y, fa(x), 2), Up(y, 1), Up(fa(x), 0), Clear(x);
	} else Set(rs(x), fa(x), 2), Up(fa(x), 0), Clear(x);
}
void Splice(int x) { // R
	Splay(x, 1); int y = fa(x); Splay(y, 0), down(x, 1);
	if (rs(y)) swap(fa(ms(x)), fa(rs(y))), swap(ms(x), rs(y)), Up(x, 1), Up(y, 0);
	else Set(ms(x), y, 1), Del(x), Up(y, 0);
}
void Access(int x) { // C
	Splay(x, 0);
	if (rs(x)) {
		int y = NewNode();
		Set(ms(x), y, 0), Set(rs(x), y, 2), Set(y, x, 2), Up(y, 1), Up(x, 0);
	}
	for (int y = x; fa(y); y = fa(y)) Splice(fa(y));
	Splay(x, 0);
}
void Makert(int x) { Access(x), Rev(x); }
void Split(int x, int y) { Makert(x), Access(y); }
void Link(int x, int y, int z) { Access(x), Makert(y), Set(y, x, 1), Set(z, y, 0), Up(y, 0), Up(x, 0); }
int n, q, eu[100005], ev[100005];
int main() {
	scanf("%d", &n), cnt = n + n - 1;
	for (int i = 1, w; i < n; ++i) scanf("%d%d%d", eu + i, ev + i, &w), f[n + i].val = f[n + i].len = w;
	for (int i = 1; i <= n; ++i) f[i].col = 1, f[i].dis[0] = f[i].dis[1] = f[i].ans = 0;
	for (int i = 1; i <= cnt; ++i) lef(i) = rig(i) = i;
	for (int i = 1; i < n; ++i) Link(eu[i], ev[i], i + n);
	scanf("%d", &q);
	int nowc = n;
	for (int $ = 1, x; $ <= q; ++$) {
		char op;
		scanf(" %c", &op);
		if (op == 'C') {
			scanf("%d", &x), Access(x), f[x].col ^= 1, Up(x, 0);
			if (f[x].col) ++nowc;
			else --nowc;
		}
		else if (op == 'A') {
			if (!nowc) puts("They have disappeared.");
			else Access(1), printf("%d\n", max(0, f[1].ans));
		}
	}
	return 0;
}
这是不那么通用的版本,写起来相对费脑子
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 1e9;
struct Node {
	int fa, ch[3];
	int lef, rig;
	int col, val;
	// 1: white, 0: black, 2: edge
	int len, dis[2], ans;
	bool rev;
	Node() {
		fa = ch[0] = ch[1] = ch[2] = lef = rig = 0;
		col = val = len = 0, dis[0] = dis[1] = ans = -inf, rev = false;
	}
	void Clear() { *this = Node(); }
} f[1000005];
int cnt, tp, st[1000005];
#define ls(x) f[x].ch[0]
#define ms(x) f[x].ch[2]
#define rs(x) f[x].ch[1]
#define fa(x) f[x].fa
#define lef(x) f[x].lef
#define rig(x) f[x].rig
void Clear(int x) { f[st[++tp] = x].Clear(); }
int NewNode() { return tp ? st[tp--] : ++cnt; }
int Get(int x) { return ls(fa(x)) == x ? 0 : (rs(fa(x)) == x ? 1 : 2); }
bool Nrt(int x) { return ls(fa(x)) == x || rs(fa(x)) == x; }
void Set(int x, int fx, int t) { if (x) f[fa(x)].ch[Get(x)] = 0, fa(x) = fx; f[fx].ch[t] = x; }
void Rev(int x) { swap(ls(x), rs(x)), swap(lef(x), rig(x)), swap(f[x].dis[0], f[x].dis[1]), f[x].rev ^= 1; }
void down(int x, int t) { if (!t && f[x].rev) Rev(ls(x)), Rev(rs(x)), f[x].rev = false; }
void Down(int x, int t) { if (Nrt(x)) Down(fa(x), t); down(x, t); }
void Up(int x, int t) {
	lef(x) = ls(x) ? lef(ls(x)) : x;
	rig(x) = rs(x) ? rig(rs(x)) : x;
	if (!t) {
		f[x].len = f[ls(x)].len + f[x].val + f[rs(x)].len;
		f[x].dis[0] = max(f[ls(x)].dis[0], f[ls(x)].len + max(f[x].col == 1 ? 0 : -inf, f[x].val + max(f[ms(x)].dis[0], f[rs(x)].dis[0])));
		f[x].dis[1] = max(f[rs(x)].dis[1], f[rs(x)].len + max(f[x].col == 1 ? 0 : -inf, f[x].val + max(f[ms(x)].dis[0], f[ls(x)].dis[1])));
		if (f[x].col == 1) f[x].dis[0] = max(f[x].dis[0], f[ls(x)].len), f[x].dis[1] = max(f[x].dis[1], f[rs(x)].len);
		f[x].ans = max({ f[ls(x)].ans, f[ms(x)].ans, f[rs(x)].ans });
		int a[3] = { f[ls(x)].dis[1], f[rs(x)].dis[0], f[ms(x)].dis[0] };
		sort(a, a + 3), f[x].ans = max(f[x].ans, a[1] + a[2]);
		if (f[x].col == 1) f[x].ans = max({ f[x].ans, a[0], a[1], a[2] });
	} else {
		f[x].len = f[ms(x)].len;
		f[x].dis[0] = max({ f[ms(x)].dis[0], f[ls(x)].dis[0], f[rs(x)].dis[0] });
		f[x].dis[1] = f[ms(x)].dis[1];
		f[x].ans = max({ f[ls(x)].ans, f[ms(x)].ans, f[rs(x)].ans });
		int a[3] = { f[ls(x)].dis[0], f[rs(x)].dis[0], f[ms(x)].dis[0] };
		sort(a, a + 3), f[x].ans = max(f[x].ans, a[1] + a[2]);
	}
}
void Rot(int x, int t) {
	int y = fa(x), z = fa(y), d = Get(x), p = f[x].ch[!d];
	if (z) f[z].ch[Get(y)] = x;
	if (p) fa(p) = y;
	fa(x) = z, f[x].ch[!d] = y, fa(y) = x, f[y].ch[d] = p, Up(y, t), Up(x, t);
}
void Splay(int x, int t, int tar = 0) {
	for (Down(x, t); Nrt(x) && fa(x) != tar; Rot(x, t))
		if (Nrt(fa(x)) && fa(fa(x)) != tar) Rot(Get(x) == Get(fa(x)) ? fa(x) : x, t);
}
void Del(int x) { // R
	if (ls(x)) {
		int y = f[ls(x)].rig;
		Splay(y, 1, x), Set(rs(x), y, 1), Set(y, fa(x), 2), Up(y, 1), Up(fa(x), 0), Clear(x);
	} else Set(rs(x), fa(x), 2), Up(fa(x), 0), Clear(x);
}
void Splice(int x) { // R
	Splay(x, 1); int y = fa(x); Splay(y, 0), down(x, 1);
	if (rs(y)) swap(fa(ms(x)), fa(rs(y))), swap(ms(x), rs(y)), Up(x, 1), Up(y, 0);
	else Set(ms(x), y, 1), Del(x), Up(y, 0);
}
void Access(int x) { // C
	Splay(x, 0);
	if (rs(x)) {
		int y = NewNode();
		Set(ms(x), y, 0), Set(rs(x), y, 2), Set(y, x, 2), Up(y, 1), Up(x, 0);
	}
	for (int y = x; fa(y); y = fa(y)) Splice(fa(y));
	Splay(x, 0);
}
void Makert(int x) { Access(x), Rev(x); }
void Split(int x, int y) { Makert(x), Access(y); }
void Link(int x, int y, int z) { Access(x), Makert(y), Set(y, x, 1), Set(z, y, 0), Up(y, 0), Up(x, 0); }
int n, q, eu[100005], ev[100005];
int main() {
	scanf("%d", &n), cnt = n + n - 1;
	for (int i = 1; i < n; ++i) scanf("%d%d%d", eu + i, ev + i, &f[n + i].val), f[n + i].col = 2, Up(n + i, 0);
	for (int i = 1; i <= n; ++i) f[i].col = 1, Up(i, 0);
	for (int i = 1; i < n; ++i) Link(eu[i], ev[i], i + n);
	scanf("%d", &q);
	int cnt = n;
	for (int $ = 1, x; $ <= q; ++$) {
		char op;
		scanf(" %c", &op);
		if (op == 'C') {
			scanf("%d", &x), Access(x), f[x].col ^= 1, Up(x, 0);
			if (f[x].col) ++cnt;
			else --cnt;
		}
		else if (op == 'A') {
			if (!cnt) puts("They have disappeared.");
			else Access(1), printf("%d\n", max(0, f[1].ans));
		}
	}
	return 0;
}

Qtree 5

跟 Qtree 4 差不多。。。甚至更简单,因为不用维护簇内答案

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 1e9;
struct Node {
	int ch[3], fa, val, type;
	// type 表示白色 / 黑色 / 边
	int lef, rig;
	int len, dis[2];
	bool rev;
	Node() { ch[0] = ch[1] = ch[2] = fa = val = type = lef = rig = len = 0, dis[0] = dis[1] = inf, rev = false; }
	void Clear() { *this = Node(); }
} f[1000005];
int cnt, tp, st[1000005];
int &ls(int x) { return f[x].ch[0]; }
int &ms(int x) { return f[x].ch[2]; }
int &rs(int x) { return f[x].ch[1]; }
int &fa(int x) { return f[x].fa; }
int &lef(int x) { return f[x].lef; }
int &rig(int x) { return f[x].rig; }
void Clear(int x) { f[st[++tp] = x].Clear(); }
int NewNode() { return tp ? st[tp--] : ++cnt; }
bool Nrt(int x) { return ls(fa(x)) == x || rs(fa(x)) == x; }
int Get(int x) { return ls(fa(x)) == x ? 0 : (rs(fa(x)) == x ? 1 : 2); }
void Set(int x, int y, int t) { if (x) f[fa(x)].ch[Get(x)] = 0, fa(x) = y; f[y].ch[t] = x; }
void Rev(int x, bool t = true) {
	f[x].rev ^= 1, swap(ls(x), rs(x)), swap(lef(x), rig(x)), swap(f[x].dis[0], f[x].dis[1]);
	if (t && f[x].rev) Rev(ls(x), false), Rev(rs(x), false), f[x].rev = false;
}
void Down(int x, int t) { if (!t && f[x].rev) Rev(ls(x)), Rev(rs(x)), f[x].rev = false; }
void Pushdown(int x, int t) { if (Nrt(x)) Pushdown(fa(x), t); Down(x, t); }
void Cpy(int x, int y) { f[x].len = f[y].len, f[x].dis[0] = f[y].dis[0], f[x].dis[1] = f[y].dis[1]; }
void Rake(int x, int y) {
	f[x].dis[0] = min(f[x].dis[0], f[y].dis[0]);
	f[x].dis[1] = min(f[x].dis[1], f[x].len + f[y].dis[0]);
}
void Compress(int x, int l, int r) {
	Node L = f[l], R = f[r];
	f[x].len = L.len + R.len;
	f[x].dis[0] = min(L.dis[0], L.len + R.dis[0]);
	f[x].dis[1] = min(R.dis[1], R.len + L.dis[1]);
}
void Pushup(int x, int t) {
	lef(x) = ls(x) ? lef(ls(x)) : x;
	rig(x) = rs(x) ? rig(rs(x)) : x;
	if (!t) {
		f[x].len = f[x].val;
		if (f[x].type) {
			f[x].dis[0] = f[x].dis[1] = 0;
		} else {
			f[x].dis[0] = f[x].dis[1] = inf;
		}
		Rake(x, ms(x));
		Compress(x, ls(x), x);
		Compress(x, x, rs(x));
	}
	else {
		Cpy(x, ms(x));
		Rake(x, ls(x));
		Rake(x, rs(x));
	}
}
void Rot(int x, int t) {
	int y = fa(x), z = fa(y), k = Get(x), p = f[x].ch[!k];
	if (p) fa(p) = y;
	if (z) f[z].ch[Get(y)] = x;
	fa(x) = z, f[x].ch[!k] = y;
	fa(y) = x, f[y].ch[k] = p;
	Pushup(y, t), Pushup(x, t);
}
void Splay(int x, int t, int tar = 0) {
	for (Pushdown(x, t); Nrt(x) && fa(x) != tar; Rot(x, t))
		if (Nrt(fa(x)) && fa(fa(x)) != tar) Rot(Get(x) == Get(fa(x)) ? fa(x) : x, t);
}
void Del(int x) { // R
	if (ls(x)) {
		int y = rig(ls(x));
		Splay(y, 1, x), Set(rs(x), y, 1), Set(y, fa(x), 2), Pushup(y, 1), Pushup(fa(x), 0), Clear(x);
	}
	else Set(rs(x), fa(x), 2), Pushup(fa(x), 0), Clear(x);
}
void Splice(int x) { // R
	Splay(x, 1); int y = fa(x); Splay(y, 0), Down(x, 1);
	if (rs(y)) swap(fa(ms(x)), fa(rs(y))), swap(ms(x), rs(y)), Pushup(x, 1), Pushup(y, 0);
	else Set(ms(x), fa(x), 1), Del(x);
}
void Access(int x) { // C
	Splay(x, 0);
	if (rs(x)) {
		int y = NewNode();
		Set(ms(x), y, 0), Set(rs(x), y, 2), Set(y, x, 2), Pushup(y, 1), Pushup(x, 0);
	}
	for (int y = x; fa(y); y = fa(y)) Splice(fa(y));
	Splay(x, 0);
}
void Makert(int x) { Access(x), Rev(x); }
void Link(int x, int y, int z) { Access(x), Makert(y), Set(y, x, 1), Set(z, y, 0), Pushup(y, 0), Pushup(x, 0); }
int n, q, nowc, eu[1000005], ev[1000005];
int main() {
	scanf("%d", &n);
	cnt = n + n - 1;
	for (int i = 1; i < n; ++i) scanf("%d%d", eu + i, ev + i), f[n + i].val = f[n + i].len = 1;
	for (int i = 1; i <= cnt; ++i) lef(i) = rig(i) = i;
	for (int i = 1; i < n; ++i) Link(eu[i], ev[i], i + n);
	scanf("%d", &q);
	for (int $ = 1; $ <= q; ++$) {
		int op; scanf("%d", &op);
		if (op == 0) {
			int i; scanf("%d", &i);
			Access(i), f[i].type ^= 1;
			if (f[i].type) ++nowc;
			else --nowc;
			Pushup(i, 0);
		}
		else if (op == 1) {
			int v; scanf("%d", &v);
			if (!nowc) puts("-1");
			else {
				Makert(v), printf("%d\n", f[v].dis[0]);
			}
		}
	}
	return 0;
}

Qtree 6

这题我第一次写完 WA 了,鸽了一个月才回头调这题调过

此题中你只需维护点信息就行了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 1e9;
int n, q;
struct Node {
	int ch[3], fa;
	int lef, rig;
	int siz;
	// 当前簇大小
	int nco;
	// 这个点的颜色
	int ans[2][2], col[2];
	// ans[0/1][0/1]: 上/下界点周围全 0/1 连通块大小
	// col[0/1]: **簇内**两个界点的颜色
	bool peq;
	// peq: 簇路径颜色是否相同
	bool rev;
	Node() {
		ch[0] = ch[1] = ch[2] = fa = lef = rig = siz = ans[0][0] = ans[0][1] = ans[1][0] = ans[1][1] = 0, rev = false;
		nco = col[0] = col[1] = 2, peq = true;
	}
	void Clear() { *this = Node(); }
} f[1000005];
int cnt, tp, st[1000005];
int &ls(int x) { return f[x].ch[0]; }
int &ms(int x) { return f[x].ch[2]; }
int &rs(int x) { return f[x].ch[1]; }
int &fa(int x) { return f[x].fa; }
int &lef(int x) { return f[x].lef; }
int &rig(int x) { return f[x].rig; }
void Clear(int x) { f[st[++tp] = x].Clear(); }
int NewNode() { return tp ? st[tp--] : ++cnt; }
bool Nrt(int x) { return ls(fa(x)) == x || rs(fa(x)) == x; }
int Get(int x) { return ls(fa(x)) == x ? 0 : (rs(fa(x)) == x ? 1 : 2); }
void Set(int x, int y, int t) { if (x) f[fa(x)].ch[Get(x)] = 0, fa(x) = y; f[y].ch[t] = x; }
void Rev(int x) { f[x].rev ^= 1, swap(ls(x), rs(x)), swap(lef(x), rig(x)), swap(f[x].ans[0], f[x].ans[1]), swap(f[x].col[0], f[x].col[1]); }
void Down(int x, int t) { if (!t && f[x].rev) Rev(ls(x)), Rev(rs(x)), f[x].rev = false; }
void Pushdown(int x, int t) { if (Nrt(x)) Pushdown(fa(x), t); Down(x, t); }
void Rake(int x, int y) {
	f[x].siz += f[y].siz;
	f[x].ans[0][0] += f[y].ans[0][0];
	f[x].ans[0][1] += f[y].ans[0][1];
}
void Compress(int x, int l, int r) {
	if (!l || !r) return;
	Node L = f[l], R = f[r];
	bool eq = L.col[1] == R.col[0];
	f[x].siz = L.siz + R.siz;
	f[x].col[0] = L.col[0];
	f[x].col[1] = R.col[1];
	for (int i : {0, 1}) {
		f[x].ans[0][i] = L.ans[0][i] + (L.peq && eq) * R.ans[0][i];
		f[x].ans[1][i] = R.ans[1][i] + (R.peq && eq) * L.ans[1][i];
	}
	f[x].peq = L.peq && R.peq && eq;
}
void Pushup(int x, int t) {
	lef(x) = ls(x) ? lef(ls(x)) : x;
	rig(x) = rs(x) ? rig(rs(x)) : x;
	if (!t) {
		int c = f[x].nco;
		f[x].siz = 1 + f[ms(x)].siz;
		f[x].col[0] = f[x].col[1] = c;
		f[x].ans[0][c] = f[x].ans[1][c] = 1 + f[ms(x)].ans[0][c];
		f[x].ans[0][!c] = f[x].ans[1][!c] = 0;
		f[x].peq = true;
		Compress(x, ls(x), x);
		Compress(x, x, rs(x));
	} else {
		f[x].siz = f[ms(x)].siz;
		for (int i : {0, 1}) {
			f[x].ans[i][0] = f[ms(x)].ans[i][0];
			f[x].ans[i][1] = f[ms(x)].ans[i][1];
			f[x].col[i] = f[ms(x)].col[i];
		}
		f[x].nco = f[ms(x)].nco;
		f[x].peq = f[ms(x)].peq;
		Rake(x, ls(x));
		Rake(x, rs(x));
	}
}
void Rot(int x, int t) {
	int y = fa(x), z = fa(y), k = Get(x), p = f[x].ch[!k];
	if (p) fa(p) = y;
	if (z) f[z].ch[Get(y)] = x;
	fa(x) = z, f[x].ch[!k] = y;
	fa(y) = x, f[y].ch[k] = p;
	Pushup(y, t), Pushup(x, t);
}
void Splay(int x, int t, int tar = 0) {
	for (Pushdown(x, t); Nrt(x) && fa(x) != tar; Rot(x, t))
		if (Nrt(fa(x)) && fa(fa(x)) != tar) Rot(Get(x) == Get(fa(x)) ? fa(x) : x, t);
}
void Del(int x) { // R
	if (ls(x)) {
		int y = rig(ls(x));
		Splay(y, 1, x), Set(rs(x), y, 1), Set(y, fa(x), 2), Pushup(y, 1), Pushup(fa(x), 0), Clear(x);
	}
	else Set(rs(x), fa(x), 2), Pushup(fa(x), 0), Clear(x);
}
void Splice(int x) { // R
	Splay(x, 1); int y = fa(x); Splay(y, 0), Down(x, 1);
	if (rs(y)) swap(fa(ms(x)), fa(rs(y))), swap(ms(x), rs(y)), Pushup(x, 1), Pushup(y, 0);
	else Set(ms(x), fa(x), 1), Del(x);
}
void Access(int x) { // C
	Splay(x, 0);
	if (rs(x)) {
		int y = NewNode();
		Set(ms(x), y, 0), Set(rs(x), y, 2), Set(y, x, 2), Pushup(y, 1), Pushup(x, 0);
	}
	for (int y = x; fa(y); y = fa(y)) Splice(fa(y));
	Splay(x, 0);
}
void Makert(int x) { Access(x), Rev(x); }
void Link(int x, int y) { Access(x), Makert(y), Set(y, x, 1), Pushup(x, 0); }
int main() {
	scanf("%d", &n), cnt = n;
	for (int i = 1; i <= n; ++i) {
		lef(i) = rig(i) = i;
		f[i].siz = 1;
		f[i].nco = 1;
		f[i].ans[0][1] = f[i].ans[1][1] = 1;
		f[i].col[0] = f[i].col[1] = 1;
		f[i].peq = true;
	}
	for (int i = 1, u, v; i < n; ++i) scanf("%d%d", &u, &v), Link(u, v);
	scanf("%d", &q);
	while (q--) {
		int op, u; scanf("%d%d", &op, &u);
		if (op == 0) {
			Makert(u), printf("%d\n", f[u].ans[0][f[u].nco]);
		} else {
			Access(u), f[u].nco ^= 1, Pushup(u, 0);
		}
	}
	return 0;
}

Qtree 7

过了 Qtree 6 后这题也相对好写。逻辑是一样的。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 2e9;
int n, m, eu[1000005], ev[1000005];
struct Dat {
	int x;
	Dat(int _x = -inf) { x = _x; }
	int operator=(const int &o) { return x = o; }
	Dat operator+(const Dat &o) { return max(x, o.x); }
	int operator+=(const Dat &o) { return x = max(x, o.x); }
};
struct Node {
	int ch[3], fa;
	int lef, rig;
	int val;
	int col;
	Dat mx[2][2];
	int co[2];
	bool rev;
	bool peq;
	Node() {
		ch[0] = ch[1] = ch[2] = fa = lef = rig = 0, rev = false;
		val = mx[0][0] = mx[0][1] = mx[1][0] = mx[1][1] = -inf;
		col = co[0] = co[1] = 2, peq = true;
	}
	void Clear() { *this = Node(); }
} f[1000005];
int cnt, tp, st[1000005];
int &ls(int x) { return f[x].ch[0]; }
int &ms(int x) { return f[x].ch[2]; }
int &rs(int x) { return f[x].ch[1]; }
int &fa(int x) { return f[x].fa; }
int &lef(int x) { return f[x].lef; }
int &rig(int x) { return f[x].rig; }
void Clear(int x) { f[st[++tp] = x].Clear(); }
int NewNode() { return tp ? st[tp--] : ++cnt; }
bool Nrt(int x) { return ls(fa(x)) == x || rs(fa(x)) == x; }
int Get(int x) { return ls(fa(x)) == x ? 0 : (rs(fa(x)) == x ? 1 : 2); }
void Set(int x, int y, int t) { if (x) f[fa(x)].ch[Get(x)] = 0, fa(x) = y; f[y].ch[t] = x; }
void Rev(int x) { f[x].rev ^= 1, swap(ls(x), rs(x)), swap(lef(x), rig(x)), swap(f[x].mx[0], f[x].mx[1]), swap(f[x].co[0], f[x].co[1]); }
void Down(int x, int t) { if (!t && f[x].rev) Rev(ls(x)), Rev(rs(x)), f[x].rev ^= 1; }
void Pushdown(int x, int t) { if (Nrt(x)) Pushdown(fa(x), t); Down(x, t); }
void Rake(int x, int y) {
	for (int i : {0, 1}) {
		f[x].mx[0][i] += f[y].mx[0][i];
		if (f[x].peq) {
			f[x].mx[1][i] += f[y].mx[0][i];
		}
	}
}
void Compress(int x, int l, int r) {
	if (!l || !r) return;
	Node L = f[l], R = f[r];
	bool eq = L.co[1] == R.co[0];
	for (int i : {0, 1}) {
		f[x].mx[0][i] = L.mx[0][i];
		f[x].mx[1][i] = R.mx[1][i];
		if (L.peq && eq) f[x].mx[0][i] += R.mx[0][i];
		if (R.peq && eq) f[x].mx[1][i] += L.mx[1][i];
	}
	f[x].co[0] = L.co[0];
	f[x].co[1] = R.co[1];
	f[x].peq = L.peq && R.peq && eq;
}
void Pushup(int x, int t) {
	lef(x) = ls(x) ? lef(ls(x)) : x;
	rig(x) = rs(x) ? rig(rs(x)) : x;
	if (!t) {
		int c = f[x].col, v = f[x].val;
		f[x].mx[0][c] = f[x].mx[1][c] = f[ms(x)].mx[0][c] + v;
		f[x].mx[0][!c] = f[x].mx[1][!c] = -inf;
		f[x].co[0] = f[x].co[1] = c;
		f[x].peq = true;
		Compress(x, ls(x), x);
		Compress(x, x, rs(x));
	} else {
		f[x].val = f[ms(x)].val;
		f[x].col = f[ms(x)].col;
		for (int i : {0, 1}) {
			for (int j : {0, 1}) 
				f[x].mx[i][j] = f[ms(x)].mx[i][j];
			f[x].co[i] = f[ms(x)].co[i];
		}
		f[x].peq = f[ms(x)].peq;
		Rake(x, ls(x));
		Rake(x, rs(x));
	}
}
void Rot(int x, int t) {
	int y = fa(x), z = fa(y), k = Get(x), p = f[x].ch[!k];
	if (p) fa(p) = y;
	if (z) f[z].ch[Get(y)] = x;
	fa(x) = z, f[x].ch[!k] = y;
	fa(y) = x, f[y].ch[k] = p;
	Pushup(y, t), Pushup(x, t);
}
void Splay(int x, int t, int tar = 0) {
	for (Pushdown(x, t); Nrt(x) && fa(x) != tar; Rot(x, t))
		if (Nrt(fa(x)) && fa(fa(x)) != tar) Rot(Get(x) == Get(fa(x)) ? fa(x) : x, t);
}
void Del(int x) { // R
	if (ls(x)) {
		int y = rig(ls(x));
		Splay(y, 1, x), Set(rs(x), y, 1), Set(y, fa(x), 2), Pushup(y, 1), Pushup(fa(x), 0), Clear(x);
	}
	else Set(rs(x), fa(x), 2), Pushup(fa(x), 0), Clear(x);
}
void Splice(int x) { // R
	Splay(x, 1); int y = fa(x); Splay(y, 0), Down(x, 1);
	if (rs(y)) {
		swap(fa(ms(x)), fa(rs(y))), swap(ms(x), rs(y)), Pushup(x, 1), Pushup(y, 0);
	}
	else Set(ms(x), y, 1), Del(x);
}
void Access(int x) { // C
	Splay(x, 0);
	if (rs(x)) {
		int y = NewNode();
		Set(ms(x), y, 0), Set(rs(x), y, 2), Set(y, x, 2), Pushup(y, 1), Pushup(x, 0);
	}
	for (int y = x; fa(y); y = fa(y)) Splice(fa(y));
	Splay(x, 0);
}
void Makert(int x) { Access(x), Rev(x); }
void Link(int x, int y) { Access(x), Makert(y), Set(y, x, 1), Pushup(x, 0); }
int main() {
	scanf("%d", &n), cnt = n;
	for (int i = 1; i < n; ++i) scanf("%d%d", eu + i, ev + i);
	for (int i = 1; i <= n; ++i) scanf("%d", &f[i].col), f[i].co[0] = f[i].co[1] = f[i].col;
	for (int i = 1; i <= n; ++i) scanf("%d", &f[i].val), f[i].mx[0][f[i].col] = f[i].val, f[i].mx[1][f[i].col] = f[i].val;
	for (int i = 1; i <= n; ++i) lef(i) = rig(i) = i;
	for (int i = 1; i < n; ++i) Link(eu[i], ev[i]);
	scanf("%d", &m);
	for (int $ = 1; $ <= m; ++$) {
		int t, u, w;
		scanf("%d%d", &t, &u);
		if (t == 0) {
			Makert(u), printf("%d\n", f[u].mx[0][f[u].col].x);
		} else if (t == 1) {
			Access(u), f[u].col ^= 1, Pushup(u, 0);
		} else if (t == 2) {
			scanf("%d", &w), Access(u), f[u].val = w, Pushup(u, 0);
		}
	}
	return 0;
}

然后我们就用 SATT 水完了 Qtree 系列所有题。。。

为了防止主题过于单一,再来两道题:

Sone 1

板子题

Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 1e9;
struct Tag {
	int k, b;
	Tag(int k = 1, int b = 0) : k(k), b(b) {}
	bool NE() { return k != 1 || b != 0; }
};
struct Dat {
	int siz, min, max, sum;
	Dat(int siz = 0, int min = inf, int max = -inf, int sum = 0) : siz(siz), min(min), max(max), sum(sum) {}
};
Tag operator+ (const Tag &x, const Tag &y) { return {x.k * y.k, x.b * y.k + y.b}; }
int operator+ (const int &x, const Tag &y) { return x * y.k + y.b; }
Dat operator+ (const Dat &x, const Tag &y) { return {x.siz, x.min == inf ? inf : x.min + y, x.max == -inf ? -inf : x.max + y, x.sum * y.k + x.siz * y.b}; }
Dat operator+ (const Dat &x, const Dat &y) { return {x.siz + y.siz, min(x.min, y.min), max(x.max, y.max), x.sum + y.sum}; }
struct Node {
	int fa, ch[3];
	int lef, rig, val;
	Dat pat, sub;
	Tag tpa, tsu;
	bool rev;
	void Clear() {
		fa = ch[0] = ch[1] = ch[2] = lef = rig = val = 0;
		rev = false, pat = sub = Dat(), tpa = tsu = Tag();
	}
} f[1000005];
int cnt, tp, st[1000005];
int &ls(int x) { return f[x].ch[0]; }
int &ms(int x) { return f[x].ch[2]; }
int &rs(int x) { return f[x].ch[1]; }
int &fa(int x) { return f[x].fa; }
int &lef(int x) { return f[x].lef; }
int &rig(int x) { return f[x].rig; }
int NewNode() { return tp ? st[tp--] : ++cnt; }
int Get(int x) { return ls(fa(x)) == x ? 0 : (rs(fa(x)) == x ? 1 : 2); }
bool Nrt(int x) { return ls(fa(x)) == x || rs(fa(x)) == x; }
void Set(int x, int fx, int t) { if (x) f[fa(x)].ch[Get(x)] = 0, fa(x) = fx; f[fx].ch[t] = x; }
void Clear(int x) { f[x].Clear(), st[++tp] = x; }
void Rev(int x) { swap(ls(x), rs(x)), swap(lef(x), rig(x)), f[x].rev ^= 1; }
void PathTag(int x, Tag w) {
	f[x].val = f[x].val + w;
	f[x].pat = f[x].pat + w;
	f[x].tpa = f[x].tpa + w;
}
void SubTag(int x, Tag w) {
	f[x].sub = f[x].sub + w;
	f[x].tsu = f[x].tsu + w;
}
void down(int x, int t) {
	if (!t) {
		if (f[x].rev) Rev(ls(x)), Rev(rs(x)), f[x].rev = false;
		if (f[x].tpa.NE()) PathTag(ls(x), f[x].tpa), PathTag(rs(x), f[x].tpa), f[x].tpa = Tag();
		if (f[x].tsu.NE()) SubTag(ls(x), f[x].tsu), SubTag(rs(x), f[x].tsu), SubTag(ms(x), f[x].tsu), f[x].tsu = Tag();
	} else {
		if (f[x].tsu.NE()) {
			SubTag(ls(x), f[x].tsu), SubTag(rs(x), f[x].tsu);
			SubTag(ms(x), f[x].tsu), PathTag(ms(x), f[x].tsu);
			f[x].tsu = Tag();
		}
	}
}
void Down(int x, int t) { if (Nrt(x)) Down(fa(x), t); down(x, t); }
void Up(int x, int t) {
	lef(x) = ls(x) ? lef(ls(x)) : x;
	rig(x) = rs(x) ? rig(rs(x)) : x;
	if (!t) {
		f[x].pat = f[ls(x)].pat + Dat(1, f[x].val, f[x].val, f[x].val) + f[rs(x)].pat;
		f[x].sub = f[ls(x)].sub + f[ms(x)].sub + f[rs(x)].sub;
	} else {
		f[x].sub = f[ls(x)].sub + f[rs(x)].sub + f[ms(x)].sub + f[ms(x)].pat;
	}
}
void Rot(int x, int t) {
	int y = fa(x), z = fa(y), d = Get(x), p = f[x].ch[!d];
	if (z) f[z].ch[Get(y)] = x;
	if (p) fa(p) = y;
	fa(x) = z, f[x].ch[!d] = y;
	fa(y) = x, f[y].ch[d] = p;
	Up(y, t), Up(x, t);
}
void Splay(int x, int t, int tar = 0) {
	for (Down(x, t); Nrt(x) && fa(x) != tar; Rot(x, t))
		if (Nrt(fa(x)) && fa(fa(x)) != tar) Rot(Get(x) == Get(fa(x)) ? fa(x) : x, t);
}
void Del(int x) { // R
	if (ls(x)) {
		int y = rig(ls(x));
		Splay(y, 1, x), Set(rs(x), y, 1), Set(y, fa(x), 2), Up(y, 1), Up(fa(x), 0), Clear(x);
	} else Set(rs(x), fa(x), 2), Up(fa(x), 0), Clear(x);
}
void Splice(int x) { // R
	Splay(x, 1); int y = fa(x); Splay(y, 0), down(x, 1);
	if (rs(y)) swap(fa(ms(x)), fa(rs(y))), swap(ms(x), rs(y)), Up(x, 1), Up(y, 0);
	else Set(ms(x), y, 1), Del(x), Up(y, 0);
}
void Access(int x) { // C
	Splay(x, 0);
	if (rs(x)) {
		int y = NewNode();
		Set(ms(x), y, 0), Set(rs(x), y, 2), Set(y, x, 2), Up(y, 1), Up(x, 0);
	}
	for (int y = x; fa(y); y = fa(y)) Splice(fa(y));
	Splay(x, 0);
}
int rt;
void Makert(int x) { Access(x), Rev(x); }
int Find(int x) { return Access(x), lef(x); }
void Split(int x, int y) { Makert(x), Access(y); }
void MPath(int x, int y, Tag w) { Split(x, y), PathTag(y, w); }
void MSub(int x, Tag w) { Split(rt, x), f[x].val = f[x].val + w, SubTag(ms(x), w), Up(x, 0); }
Dat QPath(int x, int y) { return Split(x, y), f[y].pat; }
Dat QSub(int x) { return Split(rt, x), f[ms(x)].sub + Dat(1, f[x].val, f[x].val, f[x].val); }
void Link(int x, int y) { Access(x), Makert(y), Set(y, x, 1), Up(x, 0); }
void Chgfa(int x, int y) {
	if (x == rt || x == y) return;
	Split(rt, x);
	int p = rig(ls(x));
	ls(x) = fa(ls(x)) = 0, Up(x, 0);
	if (Find(x) == Find(y)) Link(x, p);
	else Link(x, y);
}
int n, m;
int eu[100005], ev[100005];
int main() {
	scanf("%d%d", &n, &m), cnt = n;
	for (int i = 1; i < n; ++i) scanf("%d%d", eu + i, ev + i);
	for (int i = 1; i <= n; ++i) scanf("%d", &f[i].val), Up(i, 0);
	for (int i = 1; i < n; ++i) Link(eu[i], ev[i]);
	scanf("%d", &rt);
	while (m--) {
		int op, x, y, z;
		scanf("%d", &op);
		if (op == 0 || op == 5) {
			scanf("%d%d", &x, &y);
			MSub(x, {op != 0, y});
		}
		else if (op == 1) {
			scanf("%d", &rt);
		}
		else if (op == 2 || op == 6) {
			scanf("%d%d%d", &x, &y, &z);
			MPath(x, y, {op != 2, z});
		}
		else if (op == 3 || op == 4 || op == 11) {
			scanf("%d", &x);
			Dat res = QSub(x);
			if (op == 3) printf("%d\n", res.min);
			else if (op == 4) printf("%d\n", res.max);
			else printf("%d\n", res.sum);
		}
		else if (op == 7 || op == 8 || op == 10) {
			scanf("%d%d", &x, &y);
			Dat res = QPath(x, y);
			if (op == 7) printf("%d\n", res.min);
			else if (op == 8) printf("%d\n", res.max);
			else printf("%d\n", res.sum);
		}
		else if (op == 9) {
			scanf("%d%d", &x, &y);
			Chgfa(x, y);
		}
	}
	return 0;
}

Jabby's shadows

其实做完上面那些题后,这题口胡起来也相对简单。

说起来简单实际上细节相当多,还是总共花了三天 AC。。。

9K 代码谨慎食用

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m, ft[1000005], wg[1000005];
struct Node {
	int ch[3], fa;
	int lef, rig;
	int val, nco;
	int len;
	int dis[2][2]; // 上/下界点 白/黑色 的 maxdis
	int ans[2][2]; // 上/下界点所连通的 白/黑色 的 maxdis
	int col[2];
	int tag;
	int cds[2][2][2]; // 簇路径全为白/黑色时 的 dis[2][2]
	int cas[2][2][2]; // 簇路径全为白/黑色时 的 ans[2][2]
	bool rev;
	bool peq;
	Node() {
		ch[0] = ch[1] = ch[2] = fa = lef = rig = val = len = 0, peq = true, rev = false;
		nco = col[0] = col[1] = tag = 2;
		fill(cds[0][0], cds[0][0] + 8, 0);
		fill(cas[0][0], cas[0][0] + 8, 0);
		fill(dis[0], dis[0] + 4, 0);
		fill(ans[0], ans[0] + 4, 0);
	}
	void Clear() { *this = Node(); }
} f[1000005];
int cnt, tp, st[1000005];
int &ls(int x) { return f[x].ch[0]; }
int &ms(int x) { return f[x].ch[2]; }
int &rs(int x) { return f[x].ch[1]; }
int &fa(int x) { return f[x].fa; }
int &lef(int x) { return f[x].lef; }
int &rig(int x) { return f[x].rig; }
void Clear(int x) { f[st[++tp] = x].Clear(); }
int NewNode() { return tp ? st[tp--] : ++cnt; }
bool Nrt(int x) { return ls(fa(x)) == x || rs(fa(x)) == x; }
int Get(int x) { return ls(fa(x)) == x ? 0 : (rs(fa(x)) == x ? 1 : 2); }
void Set(int x, int y, int t) { if (x) f[fa(x)].ch[Get(x)] = 0, fa(x) = y; f[y].ch[t] = x; }
void Rev(int x) {
	swap(ls(x), rs(x));
	swap(lef(x), rig(x));
	swap(f[x].dis[0], f[x].dis[1]);
	swap(f[x].col[0], f[x].col[1]);
	swap(f[x].ans[0], f[x].ans[1]);
	for (int p : {0, 1}) {
		swap(f[x].cds[p][0], f[x].cds[p][1]);
		swap(f[x].cas[p][0], f[x].cas[p][1]);
	}
	f[x].rev ^= 1;
}
void Cov(int x, int c) {
	if (f[x].nco == 2) return;
	f[x].nco = f[x].col[0] = f[x].col[1] = f[x].tag = c;
	for (int p : {0, 1}) {
		for (int q : {0, 1}) {
			f[x].dis[p][q] = f[x].cds[c][p][q];
			f[x].ans[p][q] = f[x].cas[c][p][q];
		}
	}
	f[x].peq = true;
}
void Down(int x, int t) {
	if (!t && f[x].rev) Rev(ls(x)), Rev(rs(x)), f[x].rev = false;
	if (!t && f[x].tag != 2) Cov(ls(x), f[x].tag), Cov(rs(x), f[x].tag), f[x].tag = 2;
}
void Pushdown(int x, int t) {
	if (Nrt(x)) Pushdown(fa(x), t);
	Down(x, t);
}
void Rake(int x, int y) {
	for (int c : {0, 1}) {
		for (int p : {0, 1}) {
			f[x].cas[c][0][p] = max({ f[x].cas[c][0][p], f[y].ans[0][p], f[x].cds[c][0][p] + f[y].dis[0][p] });
		}
		f[x].cas[c][1][c] = max({ f[x].cas[c][1][c], f[y].ans[0][c], f[x].cds[c][0][c] + f[y].dis[0][c] });
		f[x].cas[c][1][c ^ 1] = 0;
	}
	for (int c : {0, 1}) {
		for (int p : {0, 1}) {
			f[x].cds[c][0][p] = max(f[x].cds[c][0][p], f[y].dis[0][p]);
		}
		f[x].cds[c][1][c] = max(f[x].cds[c][1][c], f[x].len + f[y].dis[0][c]);
		f[x].cds[c][1][c ^ 1] = 0;
	}
	for (int c : {0, 1}) {
		if (f[x].peq) {
			f[x].ans[1][c] = max(f[x].ans[1][c], f[x].len + f[y].dis[0][c]);
		}
		f[x].ans[0][c] = max({ f[x].ans[0][c], f[y].ans[0][c], f[x].dis[0][c] + f[y].dis[0][c] });
		f[x].dis[0][c] = max(f[x].dis[0][c], f[y].dis[0][c]);
	}
	if (f[x].peq) {
		int c = f[x].col[1];
		if (c != 2) {
			f[x].dis[1][c] = max(f[x].dis[1][c], f[x].len + f[y].dis[0][c]);
		}
	}
}
void Compress(int x, int l, int r) {
	if (!l || !r) return;
	Node L = f[l], R = f[r];
	bool eq = L.col[1] == R.col[0] || L.col[1] == 2 || R.col[0] == 2;
	for (int c : {0, 1}) {
		bool ep = eq && (L.col[1] == c || R.col[0] == c);
		f[x].dis[0][c] = L.dis[0][c];
		f[x].dis[1][c] = R.dis[1][c];
		if (L.peq && ep && R.nco != 2) f[x].dis[0][c] = max(f[x].dis[0][c], L.len + R.dis[0][c]);
		if (R.peq && ep && L.nco != 2) f[x].dis[1][c] = max(f[x].dis[1][c], R.len + L.dis[1][c]);
		if (L.nco != 2) f[x].ans[0][c] = L.ans[0][c];
		if (R.nco != 2) f[x].ans[1][c] = R.ans[1][c];
		if (L.peq && ep && R.nco != 2) f[x].ans[0][c] = max({ f[x].ans[0][c], f[x].dis[0][c], R.ans[0][c], L.dis[1][c] + R.dis[0][c] });
		if (R.peq && ep && L.nco != 2) f[x].ans[1][c] = max({ f[x].ans[1][c], f[x].dis[1][c], L.ans[1][c], R.dis[0][c] + L.dis[1][c] });
	}
	for (int c : {0, 1}) {
		f[x].cas[c][0][c ^ 1] = f[x].cas[c][1][c ^ 1] = 0;
		if (R.nco != 2) f[x].cas[c][0][c] = max({ L.cas[c][0][c], R.cas[c][0][c], L.cds[c][1][c] + R.cds[c][0][c] });
		if (L.nco != 2) f[x].cas[c][1][c] = max({ R.cas[c][1][c], L.cas[c][1][c], R.cds[c][0][c] + L.cds[c][1][c] });
		f[x].cds[c][0][c ^ 1] = f[x].cds[c][1][c ^ 1] = 0;
		f[x].cds[c][0][c] = max(L.cds[c][0][c], L.len + R.cds[c][0][c]);
		f[x].cds[c][1][c] = max(R.cds[c][1][c], R.len + L.cds[c][1][c]);
	}
	f[x].len = L.len + R.len;
	f[x].col[0] = L.col[0] != 2 ? L.col[0] : R.col[0];
	f[x].col[1] = R.col[1] != 2 ? R.col[1] : L.col[1];
	f[x].peq = L.peq && R.peq && eq;
}
void Pushup(int x, int t) {
	lef(x) = ls(x) ? lef(ls(x)) : x;
	rig(x) = rs(x) ? rig(rs(x)) : x;
	if (!t) {
		int v = f[x].val, c = f[x].nco, y = ms(x);
		f[x].len = v;
		f[x].peq = true;
		f[x].col[0] = f[x].col[1] = c;
		for (int i : {0, 1}) {
			for (int j : {0, 1}) {
				f[x].cds[i][j][i] = f[y].dis[0][i];
				f[x].cds[i][j][i ^ 1] = 0;
				f[x].cas[i][j][i] = f[y].ans[0][i];
				f[x].cas[i][j][i ^ 1] = 0;
			}
			f[x].dis[i][c] = f[y].dis[0][c];
			f[x].dis[i][c ^ 1] = 0;
			f[x].ans[i][c] = f[y].ans[0][c];
			f[x].ans[i][c ^ 1] = 0;
		}
		Compress(x, ls(x), x);
		Compress(x, x, rs(x));
	} else {
		int y = ms(x);
		f[x].val = f[y].val, f[x].nco = f[y].nco, f[x].len = f[y].len, f[x].peq = f[y].peq;
		memcpy(f[x].dis, f[y].dis, sizeof(f[x].dis));
		memcpy(f[x].ans, f[y].ans, sizeof(f[x].ans));
		memcpy(f[x].col, f[y].col, sizeof(f[x].col));
		memcpy(f[x].cds, f[y].cds, sizeof(f[x].cds));
		memcpy(f[x].cas, f[y].cas, sizeof(f[x].cas));
		Rake(x, ls(x));
		Rake(x, rs(x));
	}
}
void Rot(int x, int t) {
	int y = fa(x), z = fa(y), k = Get(x), p = f[x].ch[!k];
	if (z) f[z].ch[Get(y)] = x;
	if (p) fa(p) = y;
	fa(x) = z, f[x].ch[!k] = y;
	fa(y) = x, f[y].ch[k] = p;
	Pushup(y, t), Pushup(x, t);
}
void Splay(int x, int t, int tar = 0) {
	for (Pushdown(x, t); Nrt(x) && fa(x) != tar; Rot(x, t)) {
		if (Nrt(fa(x)) && fa(fa(x)) != tar) Rot(Get(x) == Get(fa(x)) ? fa(x) : x, t);
	}
}
void Del(int x) { // R
	if (ls(x)) {
		int y = rig(ls(x));
		Splay(y, 1, x), Set(rs(x), y, 1), Set(y, fa(x), 2), Pushup(y, 1), Pushup(fa(x), 0), Clear(x);
	}
	else Set(rs(x), fa(x), 2), Pushup(fa(x), 0), Clear(x);
}
void Splice(int x) { // R
	Splay(x, 1); int y = fa(x); Splay(y, 0), Down(x, 1);
	if (rs(y)) swap(fa(ms(x)), fa(rs(y))), swap(ms(x), rs(y)), Pushup(x, 1), Pushup(y, 0);
	else Set(ms(x), y, 1), Del(x);
}
void Access(int x) { // C
	Splay(x, 0);
	if (rs(x)) {
		int y = NewNode();
		Set(ms(x), y, 0), Set(rs(x), y, 2), Set(y, x, 2), Pushup(y, 1), Pushup(x, 0);
	}
	for (int y = x; fa(y); y = fa(y)) Splice(fa(y));
	Splay(x, 0);
}
void Makert(int x) {
	Access(x), Rev(x);
}
void Split(int x, int y) {
	Makert(x), Access(y);
}
void Link(int x, int y, int z) {
	Access(x), Makert(y), Set(y, x, 1), Set(z, y, 0), Pushup(y, 0), Pushup(x, 0);
}
int main() {
	scanf("%d", &n), cnt = n + n - 1;
	for (int i = 2; i <= n; ++i) scanf("%d", ft + i);
	for (int i = 2; i <= n; ++i) scanf("%d", wg + i);
	for (int i = 1; i <= n; ++i) {
		lef(i) = rig(i) = i;
		f[i].val = f[i].len = 0, f[i].nco = 1;
		for (int p : {0, 1}) {
			for (int q : {0, 1}) {
				f[i].cds[p][q][p] = 0;
				f[i].cds[p][q][p ^ 1] = 0;
				f[i].cas[p][q][p] = 0;
				f[i].cas[p][q][p ^ 1] = 0;
			}
			f[i].dis[p][1] = 0, f[i].dis[p][0] = 0;
			f[i].ans[p][1] = 0, f[i].ans[p][0] = 0;
		}
		f[i].col[0] = f[i].col[1] = 1;
		f[i].tag = 2;
		f[i].peq = true;
	}
	for (int i = n + 1, w; i < n + n; ++i) {
		w = wg[i - n + 1];
		lef(i) = rig(i) = i;
		f[i].val = f[i].len = w, f[i].nco = 2;
		for (int p : {0, 1}) {
			for (int q : {0, 1}) {
				f[i].cds[p][0][q] = f[i].cds[p][1][q] = 0;
				f[i].cas[p][0][q] = f[i].cas[p][1][q] = w;
			}
			f[i].dis[p][0] = f[i].dis[p][1] = 0;
			f[i].ans[p][0] = f[i].ans[p][1] = w;
		}
		f[i].col[0] = f[i].col[1] = 2;
		f[i].tag = 2;
		f[i].peq = true;
	}
	for (int i = 2; i <= n; ++i) Link(ft[i], i, i + n - 1);
	scanf("%d", &m);
	while (m--) {
		int op, u, v, c;
		scanf("%d%d", &op, &u);
		if (op == 1) {
			Makert(u);
			int ans = f[u].ans[0][f[u].nco];
			if (ans == 0) puts("QwQ");
			else printf("%d\n", ans);
		} else {
			scanf("%d%d", &v, &c);
			Split(u, v), Cov(v, (c - 1) ^ 1);
		}
	}
	return 0;
}
posted @ 2025-02-21 08:33  Laijinyi  阅读(150)  评论(0)    收藏  举报