inlineintrd(){ int x = 0; bool f = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) f |= (c == '-'); for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return f ? -x : x; }
#define N 100007 #define pb push_back
int sz[N], mxs[N];
vector<int> e[N];
voiddfs(int u, int fa){ sz[u] = 1; for (auto v : e[u]) if (v != fa) { dfs(v, u); sz[u] += sz[v]; if (sz[v] > sz[mxs[u]]) mxs[u] = v; } }
inlinevoidupd(int u){ // adding information of u into data structures }
inlinevoiddel(int u){ // deleting information of u from data structures }
voidupd(int u, int fa){ upd(u); for (auto v : e[u]) if (v != fa) upd(v, u); }
voiddel(int u, int fa){ del(u); for (auto v : e[u]) if (v != fa) del(v, u); }
voiddsu(int u, int fa){ for (auto v : e[u]) if (v != fa && v != mxs[u]) {dsu(v, u); del(v, u);} if (mxs[u]) dsu(mxs[u], u); for (auto v : e[u]) if (v != fa && v != mxs[u]) upd(v, u); upd(u); }
intmain(){ int n = rd(); for (int i = 1; i < n; ++i) { int u = rd(), v = rd(); e[u].pb(v); e[v].pb(u); } dfs(1, 1); dsu(1, 1); return0; }
CF 600 E. Lomsat gelral
一棵树每个点有一个颜色 \(c_i\)
,求每个点子树内出现次数最多的颜色的和。
对颜色维护 cnt 数组,由于 DSU
统计时只有加法,因此可以记录出现最多的次数 mx
和最多次数的颜色的和 res 。
inlineintrd(){ int x = 0; bool f = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) f |= (c == '-'); for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return f ? -x : x; }
#define N 100007 #define pb push_back
ll ans[N], res;
int cnt[N], col[N], mx;
int sz[N], mxs[N];
vector<int> e[N];
voiddfs(int u, int fa){ sz[u] = 1; for (auto v : e[u]) if (v != fa) { dfs(v, u); sz[u] += sz[v]; if (sz[v] > sz[mxs[u]]) mxs[u] = v; } }
inlinevoidupd(int u){ // adding information of u into data structures ++cnt[col[u]]; if (cnt[col[u]] > mx) {mx = cnt[col[u]]; res = col[u];} elseif (cnt[col[u]] == mx) res += col[u]; }
inlinevoiddel(int u){ // deleting information of u from data structures mx = 0; res = 0; cnt[col[u]] = 0; }
voidupd(int u, int fa){ upd(u); for (auto v : e[u]) if (v != fa) upd(v, u); }
voiddel(int u, int fa){ del(u); for (auto v : e[u]) if (v != fa) del(v, u); }
voiddsu(int u, int fa){ for (auto v : e[u]) if (v != fa && v != mxs[u]) {dsu(v, u); del(v, u);} if (mxs[u]) dsu(mxs[u], u); for (auto v : e[u]) if (v != fa && v != mxs[u]) upd(v, u); upd(u); ans[u] = res; }
intmain(){ int n = rd(); for (int i = 1; i <= n; ++i) col[i] = rd(); for (int i = 1; i < n; ++i) { int u = rd(), v = rd(); e[u].pb(v); e[v].pb(u); } dfs(1, 1); dsu(1, 1); for (int i = 1; i <= n; ++i) printf("%lld ", ans[i]); return0; }
CF 1009 F. Dominant Indices
给一棵树,对于每一个点求最小的 \(k\)
,使得子树内到他距离为 \(k\)
的点最多。
做法和上一题完全相同,每次更新的时候讨论,超过了 mx
直接覆盖 res ,等于 mx 和 res 取
\(\min\) 。
inlineintrd(){ int x = 0; bool f = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) f |= (c == '-'); for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return f ? -x : x; }
voiddfs(int u, int fa){ sz[u] = 1; dep[u] = dep[fa] + 1; for (auto v : e[u]) if (v != fa) { dfs(v, u); sz[u] += sz[v]; if (sz[v] > sz[mxs[u]]) mxs[u] = v; } }
inlinevoidupd(int u){ // adding information of u into data structures ++cnt[dep[u]]; if (cnt[dep[u]] > mx) {mx = cnt[dep[u]]; res = dep[u];} elseif (cnt[dep[u]] == mx) res = min(res, dep[u]); }
inlinevoiddel(int u){ // deleting information of u from data structures mx = 0; res = 0; cnt[dep[u]] = 0; }
voidupd(int u, int fa){ upd(u); for (auto v : e[u]) if (v != fa) upd(v, u); }
voiddel(int u, int fa){ del(u); for (auto v : e[u]) if (v != fa) del(v, u); }
voiddsu(int u, int fa){ for (auto v : e[u]) if (v != fa && v != mxs[u]) {dsu(v, u); del(v, u);} if (mxs[u]) dsu(mxs[u], u); for (auto v : e[u]) if (v != fa && v != mxs[u]) upd(v, u); upd(u); ans[u] = res - dep[u]; }
intmain(){ int n = rd(); for (int i = 1; i < n; ++i) { int u = rd(), v = rd(); e[u].pb(v); e[v].pb(u); } dfs(1, 1); dsu(1, 1); for (int i = 1; i <= n; ++i) printf("%d\n", ans[i]); return0; }
inlineintrd(){ int x = 0; bool f = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) f |= (c == '-'); for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return f ? -x : x; }
#define N 100007 #define fr first #define sc second #define pb push_back #define mp make_pair #define pii pair<int, int>
int tot, dfn[N], seq[N], top[N], dep[N], ans[N], cnt[N], fa[N];
int sz[N], mxs[N];
vector<int> son[N];
vector<pii> que[N];
voiddfs(int u){ sz[u] = 1; for (auto v : son[u]) { dfs(v); sz[u] += sz[v]; if (sz[v] > sz[mxs[u]]) mxs[u] = v; } }
voiddfs2(int u, int t){ top[u] = t; dfn[u] = ++tot; seq[tot] = u; if (mxs[u]) {dep[mxs[u]] = dep[u] + 1; dfs2(mxs[u], t);} for (auto v : son[u]) if (!dfn[v]) {dep[v] = dep[u] + 1; dfs2(v, v);} }
voidupd(int u){ ++cnt[dep[u]]; for (auto v : son[u]) upd(v); }
voiddel(int u){ --cnt[dep[u]]; for (auto v : son[u]) del(v); }
voiddsu(int u){ for (auto v : son[u]) if (v != mxs[u]) {dsu(v); del(v);} if (mxs[u]) dsu(mxs[u]); for (auto v : son[u]) if (v != mxs[u]) upd(v); ++cnt[dep[u]]; for (auto q : que[u]) ans[q.sc] = cnt[dep[u] + q.fr] - 1; }
inlineintanc(int u, int k){ if (dep[u] < k) return0; int nw = u; while (dep[u] - dep[top[nw]] < k) nw = fa[top[nw]]; return seq[dfn[nw] - (k - (dep[u] - dep[nw]))]; }
intmain(){ int n = rd(); for (int i = 1; i <= n; ++i) son[fa[i] = rd()].pb(i); for (auto u : son[0]) dfs(u); for (auto u : son[0]) dfs2(u, u); int q = rd(); for (int i = 1; i <= q; ++i) { int u = rd(), k = rd(); int w = anc(u, k); if (w == 0) continue; que[w].pb(mp(k, i)); } for (auto u : son[0]) {dsu(u); del(u);} for (int i = 1; i <= q; ++i) printf("%d ", ans[i]); return0; }
inlineintrd(){ int x = 0; bool f = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) f |= (c == '-'); for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return f ? -x : x; }
voiddfs(int u, int dep){ sz[u] = 1; stk[dep] = u; cur[dep].pb(u); dfn[u] = ++tot; for (auto v : son[u]) {dfs(v, dep + 1); sz[u] += sz[v];} for (auto [k, id] : q[u]) if (dep > k) que[dep].pb(mp(stk[dep - k], id)); }
intmain(){ int n = rd(); for (int i = 1; i <= n; ++i) son[rd()].pb(i); int m = rd(); for (int i = 1; i <= m; ++i) { int u = rd(), k = rd(); q[u].pb(mp(k, i)); } for (auto u : son[0]) dfs(u, 1); for (int i = 1; i <= n; ++i) { for (auto u : cur[i]) add(dfn[u], 1); for (auto [u, id] : que[i]) ans[id] = sum(dfn[u], dfn[u] + sz[u] - 1) - 1; for (auto u : cur[i]) add(dfn[u], -1); } for (int i = 1; i <= m; ++i) printf("%d ", ans[i]); return0; }
#define N 100007 #define fr first #define sc second #define pb push_back #define mp make_pair #define pii pair<int, int>
int dfn[N], top[N], dep[N], ans[N], tot, seq[N], fa[N];
int sz[N], mxs[N];
string nam[N];
vector<int> son[N];
vector<pii> que[N];
unordered_map<string, int> cnt[N];
voiddfs(int u){ sz[u] = 1; for (auto v : son[u]) { dfs(v); sz[u] += sz[v]; if (sz[v] > sz[mxs[u]]) mxs[u] = v; } }
voiddfs2(int u, int t){ top[u] = t; dfn[u] = ++tot; seq[tot] = u; if (mxs[u]) {dep[mxs[u]] = dep[u] + 1; dfs2(mxs[u], t);} for (auto v : son[u]) if (!dfn[v]) {dep[v] = dep[u] + 1; dfs2(v, v);} }
inlinevoidupd(int u){ // adding information of u into data structures ++cnt[dep[u]][nam[u]]; }
inlinevoiddel(int u){ // deleting information of u from data structures --cnt[dep[u]][nam[u]]; if (!cnt[dep[u]][nam[u]]) cnt[dep[u]].erase(nam[u]); }
voidupd(int u, int fa){ upd(u); for (auto v : son[u]) upd(v, u); }
voiddel(int u, int fa){ del(u); for (auto v : son[u]) del(v, u); }
voiddsu(int u, int fa){ for (auto v : son[u]) if (v != mxs[u]) {dsu(v, u); del(v, u);} if (mxs[u]) dsu(mxs[u], u); for (auto v : son[u]) if (v != mxs[u]) upd(v, u); upd(u); for (auto q : que[u]) { int d = q.fr, id = q.sc; ans[id] = cnt[dep[u] + d].size(); } }
intmain(){ cin.tie(nullptr); cout.tie(nullptr); ios::sync_with_stdio(false); int n; cin >> n; for (int i = 1; i <= n; ++i) { cin >> nam[i] >> fa[i]; son[fa[i]].pb(i); } for (auto u : son[0]) dfs(u); for (auto u : son[0]) dfs2(u, u); int q; cin >> q; for (int i = 1, u, k; i <= q; ++i) { cin >> u >> k; if (dep[u] + k > n) continue; que[u].pb(mp(k, i)); } for (auto u : son[0]) {dsu(u, u); del(u, u);} for (int i = 1; i <= q; ++i) cout << ans[i] << endl; return0; }
inlineintrd(){ int x = 0; bool f = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) f |= (c == '-'); for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return f ? -x : x; }
voiddfs(int u, int fa){ sz[u] = 1; dep[u] = dep[fa] + 1; for (auto v : son[u]) { dfs(v, u); sz[u] += sz[v]; if (sz[v] > sz[mxs[u]]) mxs[u] = v; } }
inlinevoidupd(int u){ // adding information of u into data structures ++cnt[dep[u]][ch[u]]; (cnt[dep[u]][ch[u]] & 1) ? ++odd[dep[u]] : --odd[dep[u]]; }
inlinevoiddel(int u){ // deleting information of u from data structures cnt[dep[u]][ch[u]] = odd[dep[u]] = 0; }
voidupd(int u, int fa){ upd(u); for (auto v : son[u]) if (v != fa) upd(v, u); }
voiddel(int u, int fa){ del(u); for (auto v : son[u]) if (v != fa) del(v, u); }
voiddsu(int u, int fa){ for (auto v : son[u]) if (v != fa && v != mxs[u]) {dsu(v, u); del(v, u);} if (mxs[u]) dsu(mxs[u], u); for (auto v : son[u]) if (v != fa && v != mxs[u]) upd(v, u); upd(u); for (auto [k, id] : que[u]) ans[id] = (odd[k] <= 1); }
intmain(){ int n = rd(), m = rd(); for (int i = 2; i <= n; ++i) son[rd()].pb(i); char c = getchar(); while (!isalpha(c)) c = getchar(); for (int i = 1; i <= n; ++i, c = getchar()) ch[i] = c - 'a'; for (int i = 1; i <= m; ++i) { int u = rd(), k = rd(); que[u].pb(mp(k, i)); } dfs(1, 1); dsu(1, 1); for (int i = 1; i <= m; ++i) puts(ans[i] ? "Yes" : "No"); return0; }
CF 375 D. Tree and Queries
一棵树每个点有一个颜色,每次询问 \(u_i\) 子树内出现次数超过 \(k_i\) 的颜色数。
DSU on Tree 求出来子树内颜色的出现次数 cnt 数组,再对
cnt 求出现次数 cnt' 数组,询问就是问
cnt' 的 \(k_i\)
后缀和。
inlineintrd(){ int x = 0; bool f = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) f |= (c == '-'); for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return f ? -x : x; }
voiddfs(int u, int fa){ sz[u] = 1; dep[u] = dep[fa] + 1; for (auto v : e[u]) if (v != fa) { dfs(v, u); sz[u] += sz[v]; if (sz[v] > sz[mxs[u]]) mxs[u] = v; } }
inlinevoidupd(int u){ // adding information of u into data structures ++sum[++cnt[col[u]]]; }
inlinevoiddel(int u){ // deleting information of u from data structures sum[cnt[col[u]]--]--; }
voidupd(int u, int fa){ upd(u); for (auto v : e[u]) if (v != fa) upd(v, u); }
voiddel(int u, int fa){ del(u); for (auto v : e[u]) if (v != fa) del(v, u); }
voiddsu(int u, int fa){ for (auto v : e[u]) if (v != fa && v != mxs[u]) {dsu(v, u); del(v, u);} if (mxs[u]) dsu(mxs[u], u); for (auto v : e[u]) if (v != fa && v != mxs[u]) upd(v, u); upd(u); for (auto [k, id] : que[u]) ans[id] = sum[k]; }
intmain(){ int n = rd(), m = rd(); for (int i = 1; i <= n; ++i) col[i] = rd(); for (int i = 1; i < n; ++i) { int u = rd(), v = rd(); e[u].pb(v); e[v].pb(u); } for (int i = 1; i <= m; ++i) { int u = rd(), k = rd(); que[u].pb(mp(k, i)); } dfs(1, 1); dsu(1, 1); for (int i = 1; i <= m; ++i) printf("%d\n", ans[i]); return0; }
inlineintrd(){ int x = 0; bool f = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) f |= (c == '-'); for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return f ? -x : x; }
voiddfs(int u, int fa){ sz[u] = 1; dep[u] = dep[fa] + 1; for (auto v : e[u]) if (v != fa) { dfs(v, u); sz[u] += sz[v]; if (sz[v] > sz[mxs[u]]) mxs[u] = v; } }
voidcalc(int u, int fa, int w){ for (auto v : e[u]) if (v != fa) calc(v, u, w); }
voiddsu(int u, int fa){ for (auto v : e[u]) if (v != fa && v != mxs[u]) { dsu(v, u); for (auto k : subtree[v]) cnt[a[k]][(k >> b) & 1] = 0; } if (mxs[u]) dsu(mxs[u], u); for (auto v : e[u]) if (v != fa && v != mxs[u]) { for (auto k : subtree[v]) ans += (1ll << b) * cnt[a[k] ^ a[u]][((k >> b) & 1) ^ 1]; for (auto k : subtree[v]) ++cnt[a[k]][(k >> b) & 1]; } ++cnt[a[u]][(u >> b) & 1]; }
voidget_subtree(int u, int fa, int cur){ subtree[cur].pb(u); for (auto v : e[u]) if (v != fa) get_subtree(v, u, cur); }
voiddsu_tree(int u, int fa){ for (auto v : e[u]) if (v != fa && v != mxs[u]) get_subtree(v, u, v); for (auto v : e[u]) if (v != fa) dsu_tree(v, u); }
intmain(){ int n = rd(); for (int i = 1; i <= n; ++i) a[i] = rd(); for (int i = 1; i < n; ++i) { int u = rd(), v = rd(); e[u].pb(v); e[v].pb(u); } dfs(1, 1); dsu_tree(1, 1); for (b = 0; b <= 16; ++b) { dsu(1, 1); for (int u = 1; u <= n; ++u) cnt[a[u]][0] = cnt[a[u]][1] = 0; } printf("%lld\n", ans); return0; }
CF
741 D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
一棵树每条边上有一个字符 (a - v) ,每次询问 \(u_i\)
子树内最长的简单路径,满足其上的字符重排可形成回文串。
inlineintrd(){ int x = 0; bool f = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) f |= (c == '-'); for (; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return f ? -x : x; }
voiddfs(int u, int fa, int S){ sz[u] = 1; dep[u] = dep[fa] + 1; if (u != 1) S ^= (1 << ch[u]); sta[u] = S; for (auto v : son[u]) { dfs(v, u, S); sz[u] += sz[v]; if (sz[v] > sz[mxs[u]]) mxs[u] = v; } }
inlinevoidupd(int u){ // adding information of u into data structures mxd[sta[u]] = max(mxd[sta[u]], dep[u]); }
inlinevoiddel(int u){ // deleting information of u from data structures mxd[sta[u]] = 0; res = 0; }
voidupd(int u, int fa){ upd(u); for (auto v : son[u]) if (v != fa) upd(v, u); }
voiddel(int u, int fa){ del(u); for (auto v : son[u]) if (v != fa) del(v, u); }
voidupdans(int u, int del){ // 枚举配对的状态需要保证存在!!! if (mxd[sta[u]]) res = max(res, dep[u] + mxd[sta[u]] - 2 * del); for (int i = 0; i < 22; ++i) if (mxd[sta[u] ^ (1 << i)]) res = max(res, dep[u] + mxd[sta[u] ^ (1 << i)] - 2 * del); }
voidgetans(int u, int del){ updans(u, del); for (auto v : son[u]) getans(v, del); }
voiddsu(int u, int fa){ for (auto v : son[u]) if (v != fa && v != mxs[u]) {dsu(v, u); del(v, u);} if (mxs[u]) dsu(mxs[u], u); updans(u, dep[u]); upd(u); for (auto v : son[u]) if (v != fa && v != mxs[u]) { getans(v, dep[u]); res = max(res, ans[v]); upd(v, u); } ans[u] = res; }
intmain(){ int n = rd(); for (int i = 2; i <= n; ++i) { son[rd()].pb(i); char c = getchar(); while (!isalpha(c)) c = getchar(); ch[i] = (c - 'a'); } dfs(1, 1, 0); dsu(1, 1); for (int i = 1; i <= n; ++i) printf("%d ", ans[i]); return0; }