题目传送门:https://ac.nowcoder.com/acm/contest/33188/A
题意: • 给出两棵编号 1-n 的树 A B , A B 树上每个节点均有一个权值,给出 k 个关键点的编号,问有多 少种方案使得去掉恰好一个关键点使得剩余关键点在树 A 上 LCA 的权值大于树 B 上 LCA 的权值。
思路:预处理出关键点序列的在树 A B 上的前缀 LCA 和后缀 LCA ,枚举去掉的关键节点并使用前后缀 LCA 算出剩余节点的 LCA 比较权值即可。
代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<vector>
5 #include<map>
6 #include<queue>
7 #include<set>
8 #include<cmath>
9 #include<list>
10 #include<cstring>
11 #include<string>
12 #define ll long long
13 #define ull unsigned long long
14 #define inf 0x3f3f3f3f
15 #define inff 0x7fffffff
16 using namespace std;
17 const int N = 100000 + 10;
18
19 int x[N];
20 int n, k;
21
22 struct tree {
23
24 int fa[N][31], dep[N];
25 vector<int>G[N];
26 int pre[N], suf[N];
27
28 void add(int u, int v) {
29 G[u].push_back(v);
30 }
31 void dfs(int x, int pre) {
32
33 fa[x][0] = pre;
34 dep[x] = dep[pre] + 1;
35 for (int i = 1; i <= 20; i++) {
36 fa[x][i] = fa[fa[x][i - 1]][i - 1];
37 }
38 for (int i = 0; i < G[x].size(); i++) {
39 if (G[x][i] != pre) dfs(G[x][i], x);
40 }
41
42 }
43 int lca(int x, int y) {
44
45 if (dep[x] < dep[y]) swap(x, y);
46 for (int i = 20; i >= 0; i--) {
47 if ((1 << i) <= dep[x] - dep[y]) x = fa[x][i];
48 }
49 if (x == y) return x;
50 for (int i = 20; i >= 0; i--) {
51 if (fa[x][i] != fa[y][i]) {
52 x = fa[x][i];
53 y = fa[y][i];
54 }
55 }
56
57 return fa[x][0];
58 }
59 void do_work() {
60 dfs(1, 0);
61 pre[1] = x[1];
62 for (int i = 2; i <= k; i++) {
63 pre[i] = lca(pre[i - 1], x[i]);
64 }
65 suf[k] = x[k];
66 for (int i = k - 1; i >= 1; i--) {
67 suf[i] = lca(suf[i + 1], x[i]);
68 }
69 }
70 int get_lca(int i) {
71 if (i == 1) return suf[2];
72 if (i == k) return pre[k - 1];
73 return lca(pre[i - 1], suf[i + 1]);
74 }
75
76 }treeA, treeB;
77
78
79 int wA[N], wB[N];
80
81 int main() {
82
83 ios::sync_with_stdio(false);
84 cin.tie(0), cout.tie(0);
85 cin >> n >> k;
86 for (int i = 1; i <= k; i++) {
87 cin >> x[i];
88 }
89 for (int i = 1; i <= n; i++) {
90 cin >> wA[i];
91 }
92 for (int i = 2; i <= n; i++) {
93 int u;
94 cin >> u;
95 treeA.add(u, i);
96 }
97 for (int i = 1; i <= n; i++) {
98 cin >> wB[i];
99 }
100 for (int i = 2; i <= n; i++) {
101 int u;
102 cin >> u;
103 treeB.add(u, i);
104 }
105 int ans = 0;
106 treeA.do_work();
107 treeB.do_work();
108 for (int i = 1; i <= k; i++) {
109 int la = treeA.get_lca(i);
110 int lb = treeB.get_lca(i);
111 if (wA[la] > wB[lb]) ans++;
112 }
113 cout << ans << "\n";
114
115 return 0;
116 }