1. 程式人生 > >【學習筆記】LCT link cut tree

【學習筆記】LCT link cut tree

oot 提取 安利 IV ace -- CA roo 自己

大概就是供自己復習的吧

1、 細節講解

安利兩篇blog:

  • Menci
  • 非常好的講解與題單


2、模板

把 $ rev $ 和 $ pushdown $ 的位置記清

#define lc son[x][0]
#define rc son[x][1]
#include <bits/stdc++.h>
using namespace std;
const int maxn=300009;
int son[maxn][2] ,fa[maxn], st[maxn];
int lazy[maxn], s[maxn], v[maxn];
bool
ws(int x){ return son[fa[x]][1]==x; } bool isroot(int x){ return !(son[fa[x]][0]==x||son[fa[x]][1]==x); } void update(int x){ s[x]=s[lc]^s[rc]^v[x]; } void rev(int x){ swap(lc,rc); lazy[x]^=1; } void pushdown(int x){ if(lazy[x]){ if(lc) rev(lc);
if(rc) rev(rc); lazy[x]=0; } } void rot(int x){ int f=fa[x], ff=fa[f], w1=ws(x), w2=ws(f), xx=son[x][!w1]; if(!isroot(f))son[ff][w2]=x;son[x][!w1]=f;son[f][w1]=xx; if(xx)fa[xx]=f;fa[f]=x;fa[x]=ff; update(f); } void splay(int x){ int f=x,z=0; st[++z]=f;
while(!isroot(f)) st[++z]=f=fa[f]; while(z) pushdown(st[z--]); for(;!isroot(x);rot(x)) if(!isroot(fa[x])&&ws(x)==ws(fa[x])) rot(fa[x]); update(x); } void access(int x){ for(int y=0;x;x=fa[y=x]){ splay(x), rc=y; update(x); } } void makeroot(int x){ access(x); splay(x); rev(x); } int findroot(int x){ access(x); splay(x); while(lc) pushdown(x),x=lc; return x; } void split(int x,int y){ //提取路徑 makeroot(x); access(y); splay(y); } void link(int x,int y){ //把x的爸爸設為y makeroot(x); if(findroot(y)!=x) fa[x]=y; } void cut(int x,int y){ makeroot(x); if(findroot(y)==x&&fa[x]==y&&!rc){ fa[x]=son[y][0]=0; update(y); } } int main(){ int n,m,i,op,x,y; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&v[i]); while(m--){ scanf("%d%d%d",&op,&x,&y); if(op==0) split(x,y),printf("%d\n",s[y]); if(op==1) link(x,y); if(op==2) cut(x,y); if(op==3) splay(x),v[x]=y; } return 0; }

【學習筆記】LCT link cut tree