Polycarpus got hold of a family relationship tree. The tree describes family relationships of n people, numbered 1 through n. Each person in the tree has no more than one parent.
Let’s call person a a 1-ancestor of person b, if a is the parent of b.
Let’s call person a a k-ancestor (k > 1) of person b, if person b has a 1-ancestor, and a is a (k - 1)-ancestor of b’s 1-ancestor.
Family relationships don’t form cycles in the found tree. In other words, there is no person who is his own ancestor, directly or indirectly (that is, who is an x-ancestor for himself, for some x, x > 0).
Let’s call two people x and y (x ≠ y) p-th cousins (p > 0), if there is person z, who is a p-ancestor of x and a p-ancestor of y.
Polycarpus wonders how many counsins and what kinds of them everybody has. He took a piece of paper and wrote m pairs of integers vi, pi. Help him to calculate the number of pi-th cousins that person vi has, for each pair vi, pi.
Input
The first input line contains a single integer n (1 ≤ n ≤ 105) — the number of people in the tree. The next line contains n space-separated integers r1, r2, …, rn, where ri (1 ≤ ri ≤ n) is the number of person i’s parent or 0, if person i has no parent. It is guaranteed that family relationships don’t form cycles.
The third line contains a single number m (1 ≤ m ≤ 105) — the number of family relationship queries Polycarus has. Next m lines contain pairs of space-separated integers. The i-th line contains numbers vi, pi (1 ≤ vi, pi ≤ n).
Output
Print m space-separated integers — the answers to Polycarpus’ queries. Print the answers to the queries in the order, in which the queries occur in the input.
Examples
Input
6
0 1 1 0 4 4
7
1 1
1 2
2 1
2 2
4 1
5 1
6 1
Output
0 0 1 0 0 1 1
题意·:
给你一片森林,每次询问一个点与多少个点拥有共同的K级祖先
思路:
由于是静态查询,所以莫队,线段树,树上启发式合并都可。
这里用树上启发式合并,其实也就是暴力,不过是nlogn复杂度,不过也得先处理出当前节点的k级祖先。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 6;
const int LOG = 25;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
int n, m;
int si[MAXN], hson[MAXN], dep[MAXN], anc[MAXN][LOG], cnt[MAXN], ans[MAXN];
int big;
vector<int>mp[MAXN];
vector<pair<int, int> >Q[MAXN];
void findson(int u, int pre) //找到所有的重儿子
{
si[u] = 1;
for (int i = 0; i < mp[u].size(); i++)
{
int to = mp[u][i];
if (to == pre)continue;
dep[to] = dep[u] + 1;
anc[to][0] = u;
findson(to, u);
si[u] += si[to];
if (si[to] > si[hson[u]])
hson[u] = to;
}
}
void Init(int N)
{
for (int i = 1; i < LOG; i++)
for (int j = 1; j <= N; j++)
anc[j][i] = anc[anc[j][i - 1]][i - 1];
}
int findKAncestor(int v, int k)
{
for (int i = 0; k > 0; i++)
{
if (k & 1)
v = anc[v][i];
k >>= 1;
}
return v;
}
void cal(int u, int pre, int add) //计算的过程,就是不断递归求颜色的数量
{
cnt[dep[u]] += add;
for (int i = 0; i < mp[u].size(); i++)
{
int to = mp[u][i];
if (to == pre || to == big)continue;
cal(to, u, add);
}
}
void DFS(int u, int pre, bool flag) //flag作为标记,看是轻子树还是重子树
{
for (int i = 0; i < mp[u].size(); i++) //先跑轻子树
{
int to = mp[u][i];
if (to == pre || to == hson[u])continue;
DFS(to, u, false);
}
if (hson[u]) //再跑重子树
{
DFS(hson[u], u, true);
big = hson[u];
}
cal(u, pre, 1);
big = 0;
for (int i = 0; i < Q[u].size(); i++)
ans[Q[u][i].first] = cnt[dep[u] + Q[u][i].second] - 1;
if (!flag) //如果是轻子树的话,消除影响
cal(u, pre, -1);
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
int u;
scanf("%d", &u);
mp[u].push_back(i);
mp[i].push_back(u);
}
findson(0, -1);
Init(n);
scanf("%d", &m);
for (int i = 0; i < m; i++)
{
int v, k;
scanf("%d%d", &v, &k);
v = findKAncestor(v, k);
if (!v || v == -1)
ans[i] = 0;
else
Q[v].push_back(make_pair(i, k));
}
DFS(0, -1, false);
for (int i = 0; i < m; i++)
printf("%d ", ans[i]);
return 0;
}