CF246E Blood Cousins Return [dsu on tree 树上启发式合并]
同下面一题,用map记录就好了
#include <bits/stdc++.h>
using namespace std;
// int read() {
// int x = 0;
// char c = getchar();
// while (c < 48) c = getchar();
// while (c > 47) x = x * 10 + (c - 48), c = getchar();
// return x;
//}
int n, q;
const int maxn = 2e5 + 52;
string s[maxn];
vector<int> g[maxn];
int dep[maxn], sz[maxn], son[maxn], fa[maxn];
void dfs(int u) {
sz[u] = 1;
for (int v : g[u]) {
if (v == fa[u]) continue;
fa[v] = u, dep[v] = dep[u] + 1;
dfs(v);
sz[u] += sz[v];
if (sz[v] > sz[son[u]]) son[u] = v;
}
}
int vis[maxn];
map<string, int> mp[maxn];
int sum[maxn];
void upd(string s, int dep, int qwq) {
if (qwq == 1) {
if (++mp[dep][s] == 1) ++sum[dep];
} else {
if (--mp[dep][s] == 0) --sum[dep];
}
}
void add(int u, int qwq) {
upd(s[u], dep[u], qwq);
for (int v : g[u])
if (!vis[v] && v ^ fa[u]) add(v, qwq);
}
vector<pair<int, int>> qr[maxn];
int ans[maxn];
void dfs(int u, int kep) {
for (int v : g[u])
if (v ^ fa[u] && v ^ son[u]) dfs(v, 0);
if (son[u]) dfs(son[u], 1), vis[son[u]] = 1;
add(u, 1);
vis[son[u]] = 0;
for (auto x : qr[u]) ans[x.second] = sum[x.first];
if (!kep) add(u, -1);
}
int main() {
ios ::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> s[i] >> fa[i];
g[fa[i]].push_back(i);
}
for (int i = 1; i <= n; i++)
if (!fa[i]) dfs(i);
cin >> q;
for (int i = 1; i <= q; i++) {
int x, y;
cin >> x >> y;
qr[x].push_back({ dep[x] + y, i });
}
for (int i = 1; i <= n; i++)
if (!fa[i]) dfs(i, 0);
for (int i = 1; i <= q; i++) cout << ans[i] << '\n';
return 0;
}