hihoCoder#1069 最近公共祖先·三

原题地址

根据提示用Spase Table做

将Tree先展成List,因为数组长度等于边数的2倍,树中边数等于节点数-1,所以List数组只要开2倍节点数大小即可

WA了几次,原来是查询的时候出现左边界大于右边界的情况,所以这种情况要颠倒一下

代码:

 1 #include <iostream>
 2 #include <vector>
 3 #include <string>
 4 #include <map>
 5 
 6 using namespace std;
 7 
 8 #define MAX_NODE 100005
 9 
10 int N, M;
11 map<string, int> a2i;
12 string i2a[MAX_NODE];
13 int traverse_path[MAX_NODE * 2];
14 int depth[MAX_NODE];
15 int st[MAX_NODE * 2][32]; // 保存的是节点编号
16 vector<int> child[MAX_NODE];
17 int last_position[MAX_NODE];
18 int path_length = 0;
19 int tree_size = 0;
20 
21 void traverse(int r, int d) {
22   traverse_path[path_length++] = r;
23   depth[r] = d;
24   for (auto c : child[r]) {
25     traverse(c, d + 1);
26     traverse_path[path_length++] = r;
27   }
28   last_position[r] = path_length - 1;
29 }
30 
31 void build() {
32   for (int i = 0; i < path_length; i++)
33     st[i][0] = traverse_path[i];
34 
35   for (int j = 1; (1 << j) <= path_length; j++) {
36     for (int i = 0; i + (1 << j) <= path_length; i++) {
37       int a = st[i][j - 1];
38       int b = st[i + (1 << (j - 1))][j - 1];
39       st[i][j] = depth[a] < depth[b] ? a : b;
40     }
41   }
42 }
43 
44 int query(int l, int r) {
45   if (l > r)
46     return query(r, l);
47   int len = r - l + 1;
48   int i = 0;
49   while ((1 << (i + 1)) <= len)
50     i++;
51   int a = st[l][i];
52   int b = st[r - (1 << i) + 1][i];
53   return depth[a] < depth[b] ? a : b;
54 }
55 
56 int main() {
57   scanf("%d", &N);
58   for (int i = 0; i < N; i++) {
59     string a, b;
60     int ai, bi;
61     cin >> a >> b;
62     if (a2i.find(a) == a2i.end()) {
63       ai = a2i[a] = tree_size;
64       i2a[ai] = a;
65       tree_size++;
66     }
67     else
68       ai = a2i[a];
69     if (a2i.find(b) == a2i.end()) {
70       bi = a2i[b] = tree_size;
71       i2a[bi] = b;
72       tree_size++;
73     }
74     else
75       bi = a2i[b];
76     child[ai].push_back(bi);
77   }
78 
79   traverse(0, 0);
80   build();
81 
82   scanf("%d", &M);
83   while (M--) {
84     string a, b;
85     int ai, bi;
86     cin >> a >> b;
87     ai = a2i[a];
88     bi = a2i[b];
89     cout << i2a[query(last_position[ai], last_position[bi])] << endl;
90   }
91 
92   return 0;
93 }
原文地址:https://www.cnblogs.com/boring09/p/4383056.html