Codeforces 246E Blood Cousins Return(树上启发式合并)
题目链接 Blood Cousins Return
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define rep(i, a, b) for (int i(a); i <= (b); ++i) 6 7 const int N = 200010; 8 9 string s[N]; 10 int ans[N], sz[N], h[N]; 11 bool skip[N]; 12 vector <int> v[N]; 13 vector < pair<int, int> > query[N]; 14 int n, m, x, y, q; 15 16 unordered_map <string, int> mp[N]; 17 18 void getsz(int x){ 19 sz[x] = 1; 20 for (auto u : v[x]) 21 h[u] = h[x] + 1, getsz(u), sz[x] += sz[u]; 22 } 23 24 void del(int x){ 25 auto it = mp[h[x]].find(s[x]); 26 --it->second; 27 if (!it->second) mp[h[x]].erase(it); 28 for (auto u : v[x]) if (!skip[u]) del(u); 29 } 30 31 void add(int x){ 32 mp[h[x]][s[x]]++; 33 for (auto u : v[x]) if (!skip[u]) add(u); 34 } 35 36 void dfs(int x, bool keep = 0){ 37 int mx = 0, p = 0; 38 for (auto u : v[x]) if (mx < sz[u]){ mx = sz[u]; p = u;} 39 for (auto u : v[x]) if (u != p) dfs(u, 1); 40 if (p) dfs(p), skip[p] = 1; 41 42 add(x); 43 for (auto q: query[x]) 44 ans[q.second] = mp[h[x] + q.first].size(); 45 46 if (p) skip[p] = 0; 47 if (keep) del(x); 48 } 49 50 51 int main(){ 52 53 scanf("%d", &n); 54 rep(i, 1, n){ 55 cin >> s[i] >> x; 56 v[x].push_back(i); 57 } 58 59 scanf("%d", &q); 60 rep(i, 1, q){ 61 scanf("%d%d", &x, &y); 62 query[x].push_back({y, i}); 63 } 64 65 getsz(0); 66 dfs(0); 67 68 rep(i, 1, q) printf("%d\n", ans[i]); 69 return 0; 70 }