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 }
标签:pre,suf,fa,int,多校,牛客,2022,LCA,include 来源: https://www.cnblogs.com/wabi/p/16522076.html