如何使用 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; }
本文作者:Laijinyi
本文链接:https://www.cnblogs.com/laijinyi/p/18728202
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步