欢迎光临 ~|

Laijinyi

园龄:1年7个月粉丝:2关注:2

如何使用 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 中国大陆许可协议进行许可。

posted @   Laijinyi  阅读(13)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起