Cod sursa(job #2689483)

Utilizator retrogradLucian Bicsi retrograd Data 21 decembrie 2020 02:14:11
Problema Lowest Common Ancestor Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.72 kb
#include <bits/stdc++.h>

using namespace std;


struct SplayTree {
  struct Node {
    int ch[2] = {0, 0}, p = 0;
    long long self = 0, path = 0;        // Path aggregates
    long long sub = 0, vir = 0;          // Subtree aggregates
    bool flip = 0;                       // Lazy tags
  };
  vector<Node> T;

  SplayTree(int n) : T(n + 1) {}
  
  void push(int x) {
    if (!x || !T[x].flip) return;
    int l = T[x].ch[0], r = T[x].ch[1];
    T[l].flip ^= 1, T[r].flip ^= 1;
    swap(T[x].ch[0], T[x].ch[1]);
    T[x].flip = 0;
  }
  void pull(int x) {
    int l = T[x].ch[0], r = T[x].ch[1]; push(l); push(r); 
    T[x].path = T[l].path + T[x].self + T[r].path;
    T[x].sub = T[l].sub + T[r].sub + T[x].vir + T[x].self;
  }
  void splay(int x) {
    auto set = [&](int x, int d, int y) {
      T[x].ch[d] = y; T[y].p = x; pull(x); 
    };
    auto dir = [&](int x) {
      int p = T[x].p; if (!p) return -1;
      return T[p].ch[0] == x ? 0 : T[p].ch[1] == x ? 1 : -1;
    };
    auto rotate = [&](int x) {
      int y = T[x].p, z = T[y].p, dx = dir(x), dy = dir(y);
      set(y, dx, T[x].ch[!dx]); set(x, !dx, y);
      if (~dy) set(z, dy, x); else T[x].p = z;
    };
    for (push(x); ~dir(x); ) {
      int y = T[x].p, z = T[y].p;
      push(z); push(y); push(x);
      int dx = dir(x), dy = dir(y);
      if (~dy) rotate(dx != dy ? x : y);
      rotate(x);
    }
  }
};

struct LinkCut : SplayTree {
  LinkCut(int n) : SplayTree(n) {}

  int access(int x) {
    int u = x, v = 0;
    for (; u; v = u, u = T[u].p) {
      splay(u); 
      int& ov = T[u].ch[1];
      T[u].vir += T[ov].sub - T[v].sub;
      ov = v; pull(u);
    }
    return splay(x), v;
  }
  void reroot(int x) { 
    access(x); T[x].flip ^= 1; push(x); 
  }

  void Link(int u, int v) { 
    reroot(u); access(v); 
    T[v].vir += T[u].sub;
    T[u].p = v; pull(v);
  }
  void Cut(int u, int v) {
    reroot(u); access(v);
    T[v].ch[0] = T[u].p = 0; pull(v);
  }
  bool Connected(int u, int v) {
    if (u == v) return true;
    access(u); access(v); splay(u);
    return T[v].p;
  }
  // Rooted tree LCA
  int LCA(int u, int v) { access(u); return access(v); }
  // Query subtree of u where v parent.
  long long Subtree(int u, int v) {
    reroot(u); access(v); return T[u].sub;
  }
  // Query path [u..v]
  long long Path(int u, int v) {
    reroot(u); access(v); return T[v].path;
  }
  // Update vertex with value v
  void Update(int u, long long v) {
    access(u); T[u].self = v; pull(u);
  }
};

int main() {
  ifstream cin("lca.in");
  ofstream cout("lca.out");
  int n, m; cin >> n >> m;
  LinkCut lc(n);
  for (int i = 2; i <= n; ++i) {
    int p; cin >> p; lc.Link(i, p);
  }
  for (int i = 0; i < m; ++i) {
    int a, b; cin >> a >> b;
    cout << lc.LCA(a, b) << '\n';
  }
  return 0;
}