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 }

 

你可能感兴趣的:(code)