【模板】LCT

发布时间 2023-12-13 17:28:56作者: caijianhong
P4219 [BJOI2014] 大融合
template <int N>
struct LCT {
  int ch[N + 10][2], fa[N + 10];
  bool rev[N + 10];
  int sizl[N + 10], siz[N + 10];
  bool getson(int p) { return ch[fa[p]][1] == p; }
  bool nroot(int p) { return p && ch[fa[p]][getson(p)] == p; }
  void maintain(int p) {
    if (p) siz[p] = siz[ch[p][0]] + 1 + sizl[p] + siz[ch[p][1]];
  }
  // siz[p] 有效,当且仅当 p 被 makeroot 了
  void reverse(int p) {
    swap(ch[p][0], ch[p][1]);
    rev[p] ^= 1;
  }
  void pushdown(int p) {
    if (rev[p]) {
      reverse(ch[p][0]);
      reverse(ch[p][1]);
      rev[p] = false;
    }
  }
  void pushall(int p) {
    if (nroot(p)) pushall(fa[p]);
    pushdown(p);
  }
  void rotate(int p) {
    const auto link = [&](int p, int q, int r) {
      fa[p] = q, ch[q][r] = p;
    };
    int f = fa[p], r = getson(p);
    if (nroot(f))
      link(p, fa[f], getson(f));
    else
      fa[p] = fa[f];
    link(ch[p][r ^ 1], f, r);
    link(f, p, r ^ 1);
    maintain(f);
    maintain(p);
  }
  void splay(int p) {
    pushall(p);
    for (; nroot(p); rotate(p))
      if (nroot(fa[p])) rotate(getson(p) == getson(fa[p]) ? fa[p] : p);
  }
  int access(int p) {
    int y = 0;
    for (; p; y = p, p = fa[p]) {
      splay(p);
      sizl[p] -= siz[y];
      sizl[p] += siz[ch[p][1]];
      ch[p][1] = y;
      maintain(p);
    }
    return y;
  }
  void makeroot(int p) {
    access(p);
    splay(p);
    reverse(p);
  }
  void link(int x, int y) {
    makeroot(x);
    makeroot(y);
    fa[y] = x;
    sizl[x] += siz[y];
  }
  void cut(int x, int y) {
    makeroot(x);
    access(y), splay(y);
    fa[x] = ch[y][0] = 0;
    maintain(y);
  }
};