gt22

Untitled

Aug 31st, 2019
429
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.55 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <cstdio>
  4. using namespace std;
  5.  
  6. typedef vector < vector<int> > graph;
  7.  
  8.  
  9. vector<int> lca_h, lca_dfs_list, lca_first, lca_tree;
  10. vector<char> lca_dfs_used;
  11.  
  12. void lca_dfs (const graph & g, int v, int h = 1)
  13. {
  14.     lca_dfs_used[v] = true;
  15.     lca_h[v] = h;
  16.     lca_dfs_list.push_back (v);
  17.     for (auto i = g[v].begin(); i != g[v].end(); ++i)
  18.         if (!lca_dfs_used[*i])
  19.         {
  20.             lca_dfs (g, *i, h+1);
  21.             lca_dfs_list.push_back (v);
  22.         }
  23. }
  24.  
  25. void lca_build_tree (int i, int l, int r)
  26. {
  27.     if (l == r)
  28.         lca_tree[i] = lca_dfs_list[l];
  29.     else
  30.     {
  31.         int m = (l + r) >> 1;
  32.         lca_build_tree (i+i, l, m);
  33.         lca_build_tree (i+i+1, m+1, r);
  34.         if (lca_h[lca_tree[i+i]] < lca_h[lca_tree[i+i+1]])
  35.             lca_tree[i] = lca_tree[i+i];
  36.         else
  37.             lca_tree[i] = lca_tree[i+i+1];
  38.     }
  39. }
  40.  
  41. void lca_prepare (const graph & g, int root)
  42. {
  43.     int n = (int) g.size();
  44.     lca_h.resize (n);
  45.     lca_dfs_list.reserve (n*2);
  46.     lca_dfs_used.assign (n, 0);
  47.  
  48.     lca_dfs (g, root);
  49.  
  50.     int m = (int) lca_dfs_list.size();
  51.     lca_tree.assign (lca_dfs_list.size() * 4 + 1, -1);
  52.     lca_build_tree (1, 0, m-1);
  53.  
  54.     lca_first.assign (n, -1);
  55.     for (int i = 0; i < m; ++i)
  56.     {
  57.         int v = lca_dfs_list[i];
  58.         if (lca_first[v] == -1)
  59.             lca_first[v] = i;
  60.     }
  61. }
  62.  
  63. int lca_tree_min (int i, int sl, int sr, int l, int r)
  64. {
  65.     if (sl == l && sr == r)
  66.         return lca_tree[i];
  67.     int sm = (sl + sr) >> 1;
  68.     if (r <= sm)
  69.         return lca_tree_min (i+i, sl, sm, l, r);
  70.     if (l > sm)
  71.         return lca_tree_min (i+i+1, sm+1, sr, l, r);
  72.     int ans1 = lca_tree_min (i+i, sl, sm, l, sm);
  73.     int ans2 = lca_tree_min (i+i+1, sm+1, sr, sm+1, r);
  74.     return lca_h[ans1] < lca_h[ans2] ? ans1 : ans2;
  75. }
  76.  
  77. int lca (int a, int b)
  78. {
  79.     int left = lca_first[a],
  80.             right = lca_first[b];
  81.     if (left > right)  swap (left, right);
  82.     return lca_tree_min (1, 0, (int)lca_dfs_list.size()-1, left, right);
  83. }
  84.  
  85. int main()
  86. {
  87.     freopen("lca.in", "r", stdin);
  88.     freopen("lca.out", "w", stdout);
  89.     graph g;
  90.     int n;
  91.     cin >> n;
  92.     g.resize(n, vector<int>());
  93.     for (int i = 1; i < n; ++i) {
  94.         int k;
  95.         cin >> k;
  96.         k--;
  97.         g[k].push_back(i);
  98.     }
  99.     lca_prepare (g, 0);
  100.     int m;
  101.     cin >> m;
  102.     for (int i = 0; i < m; i++)
  103.     {
  104.         int v1, v2;
  105.         cin >> v1 >> v2;
  106.         v1--;
  107.         v2--;
  108.         cout << lca(v1, v2) + 1 << endl;
  109.     }
  110. }
Advertisement
Add Comment
Please, Sign In to add comment