LCT做题笔记

  最近几天打算认真复习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 }
Link Cut Tree

洞穴勘探

   这道题用到了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

  

在美妙的数学王国中畅游

三叉神经树

由乃的OJ

维护边权的LCT

魔法森林

水管局长

维护子树信息的LCT

具有技巧性的LCT

树点涂色

猜你喜欢

转载自www.cnblogs.com/shzr/p/12000707.html
LCT