P3690 【模板】Link Cut Tree (动态树)

终于把模板写了\(QwQ\)


思路:\(LCT\)

提交:\(1\)次(当然看了题解)

题解:大佬的

自己再记录一下:
\(fa[x]\)对于每颗\(Splay\)中的根节点,记录的是\(Splay\)中在真实树中最浅的点的虚边,而其他点记录的是在\(Splay\)中的\(father\)
注意\(isroot\)这个操作,如果是\(root\)不能瞎\(rot\),因为此时的\(fa[x]\)并不是在\(Splay\)中的\(father\),而是那条虚边。
然后就是注意\(cut\)中的三个条件,缺一不可。

#include<cstdio>
#include<iostream>
#define R register int
using namespace std;
namespace Luitaryi {
namespace Fread {
static char B[1<<15],*S=B,*T=B;
inline char getchar() {return (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++);}
template<class I> inline I g(I& x) { x=0;
  register I f=1; register char ch; while(!isdigit(ch=getchar())) f=ch=='='?-1:f;
  do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
}
}using Fread::g; const int N=3e5+10;
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
int n,m,fa[N],ch[N][2],sum[N],stk[N],vl[N]; bool tg[N];
inline bool isroot(int x) {return ls(fa[x])!=x&&rs(fa[x])!=x;}
inline void upd(int x) {sum[x]=sum[ls(x)]^vl[x]^sum[rs(x)];}
inline void down(int x) {swap(ls(x),rs(x)),tg[x]^=1;}
inline void spread(int x) {if(!tg[x]) return ; if(ls(x)) down(ls(x)); if(rs(x)) down(rs(x)); tg[x]=0;}
inline void rot(int x) {
  R y=fa[x],d=ch[y][1]==x;
  if(!isroot(y)) ch[fa[y]][ch[fa[y]][1]==y]=x;
  fa[x]=fa[y]; fa[ch[y][d]=ch[x][d^1]]=y;
  fa[ch[x][d^1]=y]=x; upd(y);
}
inline void Splay(int x) {
  R y=x,top=0; stk[++top]=y;
  while(!isroot(y)) stk[++top]=y=fa[y];
  while(top) spread(stk[top]),--top;
  while(!isroot(x)) { y=fa[x];
    if(!isroot(y)) rot((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x); rot(x); 
  } upd(x);
}
inline void acc(int x) {for(R y=0;x;x=fa[y=x]) Splay(x),rs(x)=y,upd(x);}
inline void mrt(int x) {acc(x),Splay(x),down(x);} //子树中所有的深度都倒转
inline int frt(int x) {acc(x),Splay(x); while(ls(x)) spread(x),x=ls(x); Splay(x); return x;}//Splay(x)保证复杂度
inline void split(int x,int y) {mrt(x),acc(y),Splay(x);}
inline void link(int x,int y) {mrt(x); if(frt(y)!=x) fa[x]=y;}//y是x的father
inline void cut(int x,int y) {mrt(x); if(frt(y)==x&&fa[y]==x&&!ls(y)) fa[y]=rs(x)=0,upd(x);} 
inline void main() {
  g(n),g(m); for(R i=1;i<=n;++i) g(vl[i]);
  while(m--) { R op,x,y; g(op),g(x),g(y);
    if(op==0) split(x,y),printf("%d\n",sum[x]);
    if(op==1) link(x,y); if(op==2) cut(x,y); 
    if(op==3) Splay(x),vl[x]=y;
  }
} 
} signed main() {Luitaryi::main(); return 0;}

2019.08.06
94

posted @ 2019-08-06 22:02  LuitaryiJack  阅读(201)  评论(0编辑  收藏  举报