Link Cut Tree

Posted luckyblock

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Link Cut Tree相关的知识,希望对你有一定的参考价值。

//知识点 : LCT 
/*
By:Luckyblock
*/
#include <cstdio>
#include <ctype.h>
#include <algorithm>
#define ls (t[x].son[0])
#define rs (t[x].son[1])
const int kMaxn = 1e5 + 10;
//=============================================================
struct Link_Cut_Tree_Node {
  int son[2], fa;
  int xr, rev;
} t[kMaxn];
int n, m, val[kMaxn], st[kMaxn];
//=============================================================
inline int read() {
	int f = 1, w = 0; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == ‘-‘) f = -1;
	for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ ‘0‘);
	return f * w;
}
void Pushup(int x) {
  t[x].xr = t[ls].xr ^ t[rs].xr ^ val[x];
}
void PushReverse(int x) {
  std :: swap(ls, rs);
  t[x].rev ^= 1;
}
void Pushdown(int x) {
  if (! t[x].rev) return ;
  if (ls) PushReverse(ls);
  if (rs) PushReverse(rs);
  t[x].rev = 0;
}
bool IsNotRoot(int x) {
  return t[t[x].fa].son[0] == x || t[t[x].fa].son[1] == x;
}
int GetSonNum(int x) {
  return t[t[x].fa].son[1] == x;
}

void Rotate(int x) {
  int fa = t[x].fa, gfa = t[fa].fa, which_son = GetSonNum(x);
  //注意旋转顺序,在splay中这句可放在最后,但在lct中不可。
  //因为下面的两句改变了结构,无法判断原fa是否为根节点。 
	if (IsNotRoot(fa)) t[gfa].son[t[gfa].son[1] == fa] = x;  
	t[x].fa = gfa;
	
  t[fa].son[which_son] = t[x].son[which_son ^ 1];
	t[t[fa].son[which_son]].fa = fa;
	
	t[x].son[which_son ^ 1] = fa; 
  t[fa].fa = x;
	Pushup(fa);
}
void Splay(int x) {
  int now = x, cnt = 0;
  st[++ cnt] = now;
  while (IsNotRoot(now)) st[++ cnt] = (now = t[now].fa);
  while (cnt) Pushdown(st[cnt --]);
  
  
  for (int y = t[x].fa; IsNotRoot(x); Rotate(x)) {
    y = t[x].fa;
    if (IsNotRoot(y)) Rotate(GetSonNum(x) == GetSonNum(y) ? y : x);
  }
  Pushup(x);
}
void Access(int x) {
  for (int y = 0; x; y = x, x = t[x].fa) {
    Splay(x), rs = y;
    Pushup(x);
  }
}
void MakeRoot(int x) {
  Access(x);
  Splay(x);
  PushReverse(x);
}
int FindRoot(int x) {
  Access(x); Splay(x);
  while (ls) Pushdown(x), x = ls;
  Splay(x);
  return x;
}
void Split(int x, int y) {
  MakeRoot(x);
  Access(y);
  Splay(y);
}
void Cut(int x, int y) {
  MakeRoot(x);
  if(FindRoot(y) != x || t[y].fa != x || t[y].son[0]) return ;
  t[y].fa = t[x].son[1] = 0;
  Pushup(x);
}
void Link(int x, int y) {
  MakeRoot(x);
  if(FindRoot(y) != x) t[x].fa = y;
}
//=============================================================
int main() {
  n = read(), m = read();
  for (int i = 1; i <= n; ++ i) {
    t[i].xr = val[i] = read(); 
  }
  for (int i = 1; i <= m; ++ i) {
    int opt = read(), x = read(), y = read();
    if (opt == 0) {
      Split(x, y);
      printf("%d
", t[y].xr);
    }
    if (opt == 1) Link(x, y);
    if (opt == 2) Cut(x, y);
    if (opt == 3) {
      Splay(x);
      val[x] = y;
    }
  }
	return 0;
}

以上是关于Link Cut Tree的主要内容,如果未能解决你的问题,请参考以下文章

题解 luogu P1501[国家集训队]Tree II(Link-Cut-Tree)

luogu3690 模板Link Cut Tree (动态树)

Link-Cut-Tree详解

AC日记——模板Link Cut Tree 洛谷 P3690

Link Cut Tree 总结

BZOJ2555SubString(后缀自动机,Link-Cut Tree)