赞
踩
We have a rooted tree with
N
N
N vertices, numbered
1
,
2
,
…
,
N
1,2,…,N
1,2,…,N.
Vertex 1 is the root, and the parent of Vertex
i
(
2
≤
i
≤
N
)
i(2≤i≤N)
i(2≤i≤N) is Vertex
P
i
P_i
Pi.
You are given
Q
Q
Q queries. In the
i
i
i-th query
(
1
≤
i
≤
Q
)
(1≤i≤Q)
(1≤i≤Q), given integers
U
i
U_i
Ui and
D
i
D_i
Di, find the number of vertices u that satisfy all of the following conditions:
7
1 1 2 2 4 2
4
1 2
7 2
4 1
5 5
3
1
0
0
思维+DFS~
一开始我想的是倍增判断祖先,然后对该高度的所有点一一判断,但是复杂度有
O
(
n
2
l
o
g
n
)
O(n^2logn)
O(n2logn),显然不可取~
换个思维,我们可以记录一下时间戳,即 DFS 过程中进入某个点
i
i
i 的时间
i
n
[
i
]
in[i]
in[i] 和离开某个点的时间
o
u
t
[
i
]
out[i]
out[i],则对他的的祖先
j
j
j 而言,一定满足:
i
n
[
j
]
≤
i
n
[
i
]
<
o
u
t
[
j
]
in[j]\leq in[i]<out[j]
in[j]≤in[i]<out[j]
则我们可以记录每一层的
i
n
[
i
]
in[i]
in[i],对每次查询,在这一层二分找答案即可,AC代码如下:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5 + 10; int n, q, x, y, in[N], out[N], height[N], t = 0; vector<int> depth[N], G[N]; void dfs(int u) { in[u] = t++; depth[height[u]].push_back(in[u]); for (auto v:G[u]) { height[v] = height[u] + 1; dfs(v); } out[u] = t++; } int main() { scanf("%d", &n); for (int i = 2; i <= n; i++) scanf("%d", &x), G[x].push_back(i); dfs(1); scanf("%d", &q); while (q--) { scanf("%d%d", &x, &y); int l = lower_bound(depth[y].begin(), depth[y].end(), in[x]) - depth[y].begin(); int r = upper_bound(depth[y].begin(), depth[y].end(), out[x]) - depth[y].begin(); printf("%d\n", r - l); } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。