题意: 在一个森林中,如果两个节点a和b向上的第p个祖先相同,就称他们为p代表亲。(跟日常生活中有所不同,p不一定是他们的最近公共祖先)。
给出一些询问,问v的p代表亲的数量。
看起来挺麻烦,但如果我们转化一下题意,就是找一个节点的有几个同深度的子节点。
所以只需要在输入时,把题目给我们的v,p
,通过倍增转化成u,dep
,这里的dep是相对于u的。
那就是一道裸的dsu on tree 板子了。
//
// Created by SANZONG on 2021/7/6.
//
#include "bits/stdc++.h"
using namespace std;
const int maxn = 6e5;
int head[maxn << 1];
int cnt;
struct node {
int next, to;
} a[maxn << 1];
struct Query {
int p, id;
};
vector<Query> query[maxn];
int dep[maxn];
void add(int u, int v) {
a[++cnt].next = head[u];
a[cnt].to = v;
head[u] = cnt;
}
int son[maxn];
int siz[maxn];
int fath[maxn][25];
void dfsFir(int u, int fa, int deep) {
dep[u] = deep;
siz[u] = 1;
fath[u][0] = fa;
for (int i = 1; i <= 24; ++i) {
fath[u][i] = fath[fath[u][i - 1]][i - 1];
}
for (int i = head[u]; i; i = a[i].next) {
int v = a[i].to;
if (v == fa) continue;
dfsFir(v, u, deep + 1);
siz[u] += siz[v];
if (siz[v] > siz[son[u]]) {
son[u] = v;
}
}
}
int flag;
int res[maxn];
int h[maxn];
void count(int u, int fa, int val) {
h[dep[u]] += val;
for (int i = head[u]; i; i = a[i].next) {
int v = a[i].to;
if (v == fa || v == flag) continue;
count(v, u, val);
}
}
void dfsSec(int u, int fa, int keep) {
for (int i = head[u]; i; i = a[i].next) {
int v = a[i].to;
if (v == fa || v == son[u]) continue;
dfsSec(v, u, 0);
}
if (son[u]) {
dfsSec(son[u], u, 1);
flag = son[u];
}
count(u, fa, 1);
if (u != 0) {
for (Query q : query[u]) {
int id = q.id;
int dis = q.p;
// cout << id << ' ' << dis + dep[u] << ' ' << h[dis + dep[u]] << endl;
res[id] = h[dis + dep[u]] - 1;
}
}
flag = 0;
if (!keep) {
count(u, fa, -1);
}
}
int get_fa(int x, int d) {
int t = dep[x] - d; //fa的dep
for (int i = 20; i >= 0; --i) {
if (dep[fath[x][i]] > t) x = fath[x][i];
}
// cout << x << ' ' << d << ' ' << fath[x][0] << endl;
return fath[x][0];
}
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, q;
cin >> n;
for (int i = 1; i <= n; ++i) {
int u;
cin >> u;
add(i, u);
add(u, i);
}
dfsFir(0, -1, 0);
cin >> q;
for (int i = 1; i <= q; ++i) {
int v, p;
cin >> v >> p;
query[get_fa(v, p)].push_back(Query{
p, i});
}
dfsSec(0, -1, 0);
for (int i = 1; i <= q; ++i) {
cout << res[i] << endl;
}
}