最近几天打算认真复习LCT,毕竟以前只会板子。正好也可以学点新的用法,这里就用来写做题笔记吧。这个分类比较混乱,主要看感觉,不一定对;
维护森林的LCT
就是最普通,最一般那种的LCT啦。这类题目往往就是用LCT维护森林,从而快速的实现一些链上操作;其中,某些题只是维护一棵形态固定的树,用树剖也可以做,复杂度 $n\log^2n$,如果使用LCT则变成了 $n\log n$;有的题目涉及断边连边,就必须使用LCT了。这次复习做的前几道题都属于这种,这几道题的难点其实不在LCT上,只要会敲模板就OK了,可以稍微练习码力。正好这次就顺便把以前做过的题一起整理一下吧~
[模板]Link Cut Tree
是一道小清新的模板题呢,只用到了一些基础的操作,没有区间修改这类稍微复杂的东西。
1 # include <cstdio> 2 # include <iostream> 3 # include <cstring> 4 # include <string> 5 # define R register int 6 # define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++) 7 8 using namespace std; 9 10 const int maxn=300010; 11 int n,m,opt,x,y; 12 int v[maxn],ch[maxn][2],f[maxn],sta[maxn],Tp,s[maxn],rev[maxn]; 13 char BB[1 << 18], *S = BB, *T = BB; 14 15 int read() 16 { 17 R x=0; 18 char c=getchar(); 19 while (!isdigit(c)) c=getchar(); 20 while (isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar(); 21 return x; 22 } 23 24 bool rt (int x) { return (ch[ f[x] ][0]==x||ch[ f[x] ][1]==x); } //x是所在splay的根吗? 25 void update (int x) { s[x]=v[x]^s[ ch[x][0] ]^s[ ch[x][1] ]; } 26 void swp (int x) { rev[x]^=1; swap(ch[x][0],ch[x][1]); } 27 void pushdown (int x) 28 { 29 if(rev[x]==0) return ; 30 if(ch[x][0]) swp(ch[x][0]); 31 if(ch[x][1]) swp(ch[x][1]); 32 rev[x]=0; 33 } 34 35 void rotate (int x) 36 { 37 int fx=f[x],ff=f[fx],k=(ch[fx][1]==x),t=ch[x][k^1]; 38 if(rt(fx)) ch[ff][ ch[ff][1]==fx ]=x; 39 ch[fx][k]=t,ch[x][k^1]=fx,f[fx]=x,f[x]=ff; 40 if(t) f[t]=fx; 41 update(fx); 42 } 43 44 void splay (int x) //把x转到自己所在splay的根上去 45 { 46 Tp=0,sta[++Tp]=x; 47 int y=x; 48 while(rt(y)) sta[++Tp]=(y=f[y]); 49 for (R i=Tp;i>=1;--i) pushdown(sta[i]); 50 int fx,ff; 51 while(rt(x)) 52 { 53 fx=f[x],ff=f[fx]; 54 if(rt(fx)) rotate(((ch[fx][0]==x)!=(ch[ff][0]==fx))?x:fx); 55 rotate(x); 56 } 57 update(x); 58 } 59 60 int ws (int x) { return (ch[ f[x] ][1]==x); } //x是父亲的哪个孩子? 61 void access (int x) 62 { 63 for (R y=0;x;y=x,x=f[x]) 64 splay(x),ch[x][1]=y,update(x); 65 } 66 67 void change_root (int x) { access(x); splay(x); swp(x); } 68 int find (int x) 69 { 70 access(x),splay(x); 71 while(ch[x][0]) pushdown(x),x=ch[x][0]; 72 return x; 73 } 74 75 void link (int x,int y) 76 { 77 change_root(x); 78 if(find(y)!=x) f[x]=y; 79 } 80 81 void cut (int x,int y) 82 { 83 change_root(x); 84 if(find(y)!=x||f[x]!=y||ch[x][1]) return ; 85 f[x]=ch[y][0]=0; 86 update(y); 87 } 88 89 void split (int x,int y) 90 { 91 change_root(x); 92 access(y),splay(y); 93 } 94 95 void write (int x) 96 { 97 if(x>=10) write(x/10); 98 putchar(x%10+'0'); 99 } 100 101 int main() 102 { 103 n=read(),m=read(); 104 for (R i=1;i<=n;++i) v[i]=read(); 105 for (R i=1;i<=m;++i) 106 { 107 opt=read(),x=read(),y=read(); 108 if(opt==0) split(x,y),write(s[y]),putchar('\n'); 109 else if(opt==1) link(x,y); 110 else if(opt==2) cut(x,y); 111 else if(opt==3) splay(x),v[x]=y; 112 } 113 return 0; 114 }
洞穴勘探
这道题用到了findroot来判断连通性。不过这是2008年的题,那时候LCT还没有特别普及吧,不知道当年的标算是什么?
1 # include <cstdio> 2 # include <iostream> 3 # include <cstring> 4 # include <string> 5 # define R register int 6 7 using namespace std; 8 9 const int maxn=10005; 10 int n,m,x,y,F[maxn],ch[maxn][2],t[maxn],st[maxn],Tp; 11 char c[10]; 12 13 inline bool isnt_rt (int x) { return ch[ F[x] ][0]==x||ch[ F[x] ][1]==x; } 14 inline void rev (int x) { swap(ch[x][0],ch[x][1]); t[x]^=1; } 15 inline void pushdown (int x) { if(t[x]) rev(ch[x][0]),rev(ch[x][1]),t[x]=0; } 16 inline int D (int x) { return ch[ F[x] ][1]==x; } 17 18 inline void rotate (int x) 19 { 20 int f=F[x],g=F[f],dx=D(x),df=D(F[x]); 21 int k=ch[x][dx^1]; 22 if(isnt_rt(f)) ch[g][df]=x; 23 ch[f][dx]=k; 24 ch[x][dx^1]=f; 25 if(k) F[k]=f; 26 F[f]=x; F[x]=g; 27 } 28 29 inline void splay (int x) 30 { 31 // printf("splay(%d)\n",x); 32 int t=x,f,g; 33 st[++Tp]=t; 34 while (isnt_rt(t)) st[++Tp]=F[t],t=F[t]; 35 while (Tp) pushdown(st[Tp]),Tp--; 36 while (isnt_rt(x)) 37 { 38 f=F[x],g=F[f]; 39 if(isnt_rt(f)) 40 { 41 if(D(x)==D(f)) rotate(f); 42 else rotate(x); 43 } 44 rotate(x); 45 } 46 } 47 48 inline void access (int x) 49 { 50 // printf("access(%d)\n",x); 51 for (int y=0;x;y=x,x=F[x]) 52 splay(x),ch[x][1]=y; 53 } 54 55 inline void makeroot (int x) 56 { 57 // printf("makeroot(%d)\n",x); 58 access(x); 59 splay(x); 60 rev(x); 61 } 62 63 inline int findroot (int x) 64 { 65 // printf("findroot(%d)\n",x); 66 access(x),splay(x); 67 while(ch[x][0]) pushdown(x),x=ch[x][0]; 68 splay(x); 69 return x; 70 } 71 72 inline void link (int x,int y) 73 { 74 // printf("link(%d %d)\n",x,y); 75 makeroot(x); 76 if(findroot(y)!=x) F[x]=y; 77 access(y); 78 } 79 80 inline void cut (int x,int y) 81 { 82 // printf("cut(%d %d)\n",x,y); 83 makeroot(x); 84 access(y); 85 splay(y); 86 F[x]=0,ch[y][0]=0; 87 } 88 89 int main() 90 { 91 scanf("%d%d",&n,&m); 92 for (R i=1;i<=m;++i) 93 { 94 scanf("%s",c+1); 95 scanf("%d%d",&x,&y); 96 if (c[1]=='Q') 97 { 98 if(findroot(x)==findroot(y)) printf("Yes\n"); 99 else printf("No\n"); 100 } 101 else if (c[1]=='C') 102 link(x,y); 103 else if (c[1]=='D') 104 cut(x,y); 105 } 106 return 0; 107 }
Tree II