题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805343727501312
题意:
给定一个二叉搜索树,以及他的前序遍历序列。
现在有m组询问,对于给定的两个关键字值u,v问他们的最近公共祖先是谁。
思路:
根本跟LCA都没关系好吗。m不是很大,每组询问都查找一次u和v就行了。
因为是BST所以根据前序序列可以直接建出这棵树。
然后在树上查找u和v。
本来还用了一个vector分别存根到u,v的路径,然后两个循环暴力找到最近公共祖先。然后超时了。
其实根本不用这么麻烦,只用在查找的过程中用一个vis数组来标记上一次查找是否已经经过这个点了。如果已经访问过,那么说明这个祖先是他们公共的,更新答案。
因为是从顶开始的遍历所以最后结束时的答案肯定是最近的公共祖先。
1 //#include<bits/stdc++> 2 #include<stdio.h> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstring> 6 #include<stdlib.h> 7 #include<queue> 8 #include<map> 9 #include<stack> 10 #include<set> 11 12 #define LL long long 13 #define ull unsigned long long 14 #define inf 0x3f3f3f3f 15 16 using namespace std; 17 18 int n, m; 19 const int maxn = 1e4 + 5; 20 int preorder[maxn]; 21 22 struct node{ 23 int lchild = -1, rchild = -1; 24 int key; 25 }tree[maxn]; 26 int tot = 1; 27 28 bool Insert(int val, int rt) 29 { 30 if(val < tree[rt].key){ 31 if(tree[rt].lchild == -1){ 32 tree[tot].key = val; 33 tree[rt].lchild = tot++; 34 return true; 35 } 36 else return Insert(val, tree[rt].lchild); 37 } 38 else if(val > tree[rt].key){ 39 if(tree[rt].rchild == -1){ 40 tree[tot].key = val; 41 tree[rt].rchild = tot++; 42 return true; 43 } 44 else return Insert(val, tree[rt].rchild); 45 } 46 else return true; 47 } 48 49 //vector<int>path[2]; 50 int vis[maxn], ans; 51 bool ffind(int val) 52 { 53 // path[u].clear(); 54 //memset(vis, 0, sizeof(vis)); 55 int now = 1; 56 while(now != -1){ 57 if(tree[now].key == val){ 58 if(vis[now])ans = now; 59 else vis[now] = true; 60 // path[u].push_back(now); 61 return true; 62 } 63 else if(val < tree[now].key){ 64 if(vis[now])ans = now; 65 else vis[now] = true; 66 // path[u].push_back(now); 67 now = tree[now].lchild; 68 } 69 else if(val > tree[now].key){ 70 if(vis[now])ans = now; 71 else vis[now] = true; 72 // path[u].push_back(now); 73 now = tree[now].rchild; 74 } 75 } 76 if(now == -1)return false; 77 } 78 79 void printtree(int rt) 80 { 81 if(rt == -1)return; 82 printf("%d ", tree[rt].key); 83 printtree(tree[rt].lchild); 84 printtree(tree[rt].rchild); 85 return; 86 } 87 88 int main() 89 { 90 scanf("%d%d", &m, &n); 91 tree[0].key = inf; 92 for(int i = 0; i < n; i++){ 93 scanf("%d", &preorder[i]); 94 Insert(preorder[i], 0); 95 } 96 //printtree(1); 97 while(m--){ 98 int u, v; 99 scanf("%d%d", &u, &v); 100 ans = -1; 101 memset(vis, 0, sizeof(vis)); 102 bool fu = ffind(u); 103 bool fv = ffind(v); 104 if(!fu && !fv){ 105 printf("ERROR: %d and %d are not found. ", u, v); 106 } 107 else if(!fu){ 108 printf("ERROR: %d is not found. ", u); 109 } 110 else if(!fv){ 111 printf("ERROR: %d is not found. ", v); 112 } 113 else{ 114 // for(int i = 0; i < path[0].size(); i++)printf("%d ", tree[path[0][i]].key);printf(" "); 115 // for(int j = 0; j < path[1].size(); j++)printf("%d ", tree[path[1][j]].key);printf(" "); 116 117 if(tree[ans].key == u){ 118 printf("%d is an ancestor of %d. ", u, v); 119 } 120 else if(tree[ans].key == v){ 121 printf("%d is an ancestor of %d. ", v, u); 122 } 123 else if(ans != -1){ 124 printf("LCA of %d and %d is %d. ", u, v, tree[ans].key); 125 } 126 } 127 } 128 129 return 0; 130 }