之前以为很恐怖,学了之后发现没有想象中的难
关键还是长长见识,了解能够应用的方面
两个题单,慢慢刷:
目前的模板:
(UPD:2020.8.13更新,针对多测优化了一下)
const int N=300005; //在struct外遍历树上节点一定要pushdown! struct LinkCutTree { int fa[N],ch[N][2]; bool isroot[N]; int rev[N]; void init(int n) { for(int i=1;i<=n;i++) fa[i]=ch[i][0]=ch[i][1]=rev[i]=0,isroot[i]=true; } void pushdown(int x) { int &l=ch[x][0],&r=ch[x][1]; if(rev[x]) { swap(l,r); rev[l]^=1; rev[r]^=1; rev[x]=0; } } //取决于要维护的东西 看是否要pushdown两层 void push(int x) { if(!isroot[x]) push(fa[x]); pushdown(x); } //维护Splay中的信息 void pushup(int x) { /*维护子树/连通块大小 if(x) sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+si[x]+1;*/ } void rotate(int x) { int f=fa[x],ff=fa[f]; int dir=(ch[f][1]==x); swap(isroot[x],isroot[f]); if(!isroot[x]) ch[ff][ch[ff][1]==f]=x; fa[x]=ff; ch[f][dir]=ch[x][dir^1]; fa[ch[x][dir^1]]=f; ch[x][dir^1]=f; fa[f]=x; pushup(f),pushup(x); } void splay(int x) { push(x); while(!isroot[x]) { int f=fa[x],ff=fa[f]; if(!isroot[f]) rotate((ch[f][1]==x)==(ch[ff][1]==f)?f:x); rotate(x); } } //访问x 返回新根 int access(int x) { int y=0; while(x) { splay(x); //si[x]=si[x]-sz[y]+sz[ch[x][1]];//维护子树/连通块大小 isroot[ch[x][1]]=true; isroot[ch[x][1]=y]=false; pushup(y),pushup(x); y=x,x=fa[x]; } return y; } //将x置为根 void makeroot(int x) { access(x); splay(x); rev[x]^=1; } //连接x,y void link(int x,int y) { makeroot(x); //makeroot(y);//维护子树/连通块大小 fa[x]=y; //si[y]+=sz[x];//维护子树/连通块大小 pushup(y); } //断开x,y void cut(int x,int y) { makeroot(x); access(y); splay(y); fa[x]=ch[y][0]=0; isroot[x]=true; pushup(y); } //判断x,y是否相连 bool same(int x,int y) { makeroot(x); while(fa[y]) y=fa[y]; return x==y; } };