2022牛客暑期多校训练营3-A.Ancestor(LCA)

题目传送门: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 }

 

 
 
posted @ 2022-07-26 18:17  Keyzee  阅读(30)  评论(0编辑  收藏  举报