• LCT总结


    [ZJOI2008]树的统计Count

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<string>
      6 #include<ctime>
      7 #include<cmath>
      8 #include<set>
      9 #include<map>
     10 #include<queue>
     11 #include<algorithm>
     12 #include<iomanip>
     13 using namespace std;
     14 #define FILE "dealing"
     15 #define up(i,j,n) for(int i=(j);i<=(n);i++)
     16 #define pii pair<int,int>
     17 #define LL long long
     18 namespace IO{
     19     char buf[1<<15],*fs,*ft;
     20     int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;}
     21     int read(){
     22         int ch=gc(),f=0,x=0;
     23         while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();}
     24         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();}
     25         return f?-x:x;
     26     }
     27     int readint(){
     28         int ch=getchar(),f=0,x=0;
     29         while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
     30         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
     31         return f?-x:x;
     32     }
     33 }using namespace IO;
     34 const int maxn=31000,inf=100000000;
     35 int n,m,top=0;
     36 int c[maxn][2],siz[maxn],rev[maxn];
     37 int fa[maxn],u[maxn],v[maxn],q[maxn];
     38 LL w[maxn],sum[maxn],mx[maxn];
     39 inline bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
     40 void updata(int x){
     41     sum[x]=sum[c[x][1]]+sum[c[x][0]]+w[x];
     42     mx[x]=max(w[x],max(mx[c[x][1]],mx[c[x][0]]));
     43 }
     44 void pushdown(int x){
     45     if(rev[x]){
     46         rev[x]^=1,rev[c[x][0]]^=1,rev[c[x][1]]^=1;
     47         swap(c[x][0],c[x][1]);
     48     }
     49 }
     50 void rotate(int x){
     51     int y=fa[x],z=fa[y],l;
     52     l=(c[y][1]==x);
     53     if(!isroot(y))c[z][c[z][1]==y]=x;
     54     fa[c[x][l^1]]=y;fa[y]=x;fa[x]=z;
     55     c[y][l]=c[x][l^1];c[x][l^1]=y;
     56     updata(y);updata(x);
     57 }
     58 void splay(int x){
     59     q[++top]=x;
     60     for(int i=x;!isroot(i);i=fa[i])
     61         q[++top]=fa[i];
     62     while(top)pushdown(q[top--]);
     63     while(!isroot(x)){
     64         int y=fa[x],z=fa[y];
     65         if(!isroot(y)){
     66             if(c[y][0]==x^c[z][0]==y)rotate(x);
     67             else rotate(y);
     68         }
     69         rotate(x);
     70     }
     71 }
     72 void access(int x){
     73     for(int t=0;x;t=x,x=fa[x])
     74         splay(x),c[x][1]=t,updata(x);
     75 }
     76 void makeroot(int x){
     77     access(x);
     78     splay(x);
     79     rev[x]^=1;
     80 }
     81 void link(int x,int y){
     82     makeroot(x);
     83     fa[x]=y;
     84 }
     85 void split(int x,int y){
     86     makeroot(x);
     87     access(y);
     88     splay(y);
     89 }
     90 char s[10];int x,y;
     91 int main(){
     92     n=readint();mx[0]=-inf;
     93     up(i,1,n-1)u[i]=readint(),v[i]=readint();
     94     up(i,1,n)mx[i]=sum[i]=w[i]=readint();
     95     up(i,1,n-1)link(u[i],v[i]);
     96     m=readint();
     97     while(m--){
     98         scanf("%s",s);x=readint(),y=readint();
     99         if(s[1]=='H'){
    100             splay(x);w[x]=y;updata(x);
    101         }
    102         else if(s[1]=='M')split(x,y),printf("%lld
    ",mx[y]);
    103         else split(x,y),printf("%lld
    ",sum[y]);
    104     }
    105     return 0;
    106 }
    View Code

    [sdoi2011] 染色

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<string>
      6 #include<ctime>
      7 #include<cmath>
      8 #include<set>
      9 #include<map>
     10 #include<queue>
     11 #include<algorithm>
     12 #include<iomanip>
     13 using namespace std;
     14 #define FILE "dealing"
     15 #define up(i,j,n) for(int i=(j);i<=(n);i++)
     16 #define pii pair<int,int>
     17 #define LL int
     18 #define mem(f,g) memset(f,g,sizeof(f))
     19 namespace IO{
     20     char buf[1<<15],*fs,*ft;
     21     int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;}
     22     int read(){
     23         int ch=gc(),f=0,x=0;
     24         while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();}
     25         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();}
     26         return f?-x:x;
     27     }
     28     int readint(){
     29         int ch=getchar(),f=0,x=0;
     30         while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
     31         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
     32         return f?-x:x;
     33     }
     34 }using namespace IO;
     35 const int maxn=201000,inf=100000000;
     36 int n,m,top;
     37 int fa[maxn],sum[maxn],l[maxn],r[maxn],v[maxn],f[maxn],c[maxn][2],q[maxn],rev[maxn];
     38 void updata(int x){
     39     sum[x]=1;
     40     if(c[x][0])sum[x]+=sum[c[x][0]]-(v[x]==r[c[x][0]]),l[x]=l[c[x][0]];
     41     else l[x]=v[x];
     42     if(c[x][1])sum[x]+=sum[c[x][1]]-(v[x]==l[c[x][1]]),r[x]=r[c[x][1]];
     43     else r[x]=v[x];
     44 }
     45 void change(int x,int d){
     46     l[x]=r[x]=v[x]=f[x]=d;
     47     sum[x]=1;
     48 }
     49 void w(int x){swap(l[x],r[x]);}
     50 void pushdown(int x){
     51     if(rev[x]){
     52         rev[x]^=1,rev[c[x][0]]^=1,rev[c[x][1]]^=1;
     53         w(c[x][0]);w(c[x][1]);
     54         swap(c[x][0],c[x][1]);
     55         updata(x);
     56     }
     57     if(f[x]!=-1){
     58         if(c[x][0])change(c[x][0],f[x]);
     59         if(c[x][1])change(c[x][1],f[x]);
     60         f[x]=-1;
     61     }
     62 }
     63 bool isroot(int x){
     64     return c[fa[x]][1]!=x&&c[fa[x]][0]!=x;
     65 }
     66 void rotate(int x){
     67     int d,y=fa[x],z=fa[y];
     68     d=(c[y][1]==x);
     69     if(!isroot(y))c[z][c[z][1]==y]=x;
     70     fa[x]=z;fa[y]=x;fa[c[x][d^1]]=y;
     71     c[y][d]=c[x][d^1];c[x][d^1]=y;
     72     updata(y);updata(x);
     73 }
     74 void splay(int x){
     75     q[++top]=x;
     76     for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
     77     while(top)pushdown(q[top--]);
     78     while(!isroot(x)){
     79         int y=fa[x],z=fa[y];
     80         if(!isroot(y)){
     81             if((c[y][1]==x)^(c[z][1]==y))rotate(y);
     82             else rotate(x);
     83         }
     84         rotate(x);
     85     }
     86 }
     87 void access(int x){
     88     for(int t=0;x;t=x,x=fa[x])splay(x),c[x][1]=t,updata(x);
     89 }
     90 void makeroot(int x){
     91     access(x);splay(x);rev[x]^=1;swap(l[x],r[x]);
     92 }
     93 void link(int x,int y){
     94     makeroot(x);fa[x]=y;splay(x);
     95 }
     96 int x,y,z;
     97 char s;
     98 int main(){
     99     //freopen(FILE".in","r",stdin);
    100     //freopen(FILE".out","w",stdout);
    101     n=readint(),m=readint();
    102     mem(f,-1);mem(l,-1);mem(r,-1);mem(v,-1);
    103     up(i,1,n)l[i]=v[i]=r[i]=readint();
    104     up(i,1,n-1){
    105         x=readint(),y=readint();
    106         link(x,y);
    107     }
    108     while(m--){
    109         scanf(" %c",&s);x=readint(),y=readint();
    110         if(s=='Q'){
    111             makeroot(x);
    112             access(y);
    113             splay(y);
    114             printf("%d
    ",sum[y]);
    115         }
    116         else {
    117             makeroot(x);
    118             access(y);
    119             splay(y);
    120             z=readint();
    121             change(y,z);
    122             splay(x);
    123         }
    124     }
    125     return 0;
    126 }
    View Code

    [SDOI2008]洞穴勘测

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<string>
      6 #include<ctime>
      7 #include<cmath>
      8 #include<set>
      9 #include<map>
     10 #include<queue>
     11 #include<algorithm>
     12 #include<iomanip>
     13 using namespace std;
     14 #define FILE "dealing"
     15 #define up(i,j,n) for(int i=(j);i<=(n);i++)
     16 #define pii pair<int,int>
     17 #define LL long long
     18 namespace IO{
     19     char buf[1<<15],*fs,*ft;
     20     int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;}
     21     int read(){
     22         int ch=gc(),f=0,x=0;
     23         while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();}
     24         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();}
     25         return f?-x:x;
     26     }
     27     int readint(){
     28         int ch=getchar(),f=0,x=0;
     29         while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
     30         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
     31         return f?-x:x;
     32     }
     33 }using namespace IO;
     34 const int maxn=101000,inf=100000000;
     35 int n,m,top=0;
     36 int c[maxn][2],siz[maxn],rev[maxn];
     37 int fa[maxn],u[maxn],v[maxn],q[maxn];
     38 LL w[maxn],sum[maxn],mx[maxn];
     39 inline bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
     40 void pushdown(int x){
     41     if(rev[x]){
     42         rev[x]^=1,rev[c[x][0]]^=1,rev[c[x][1]]^=1;
     43         swap(c[x][0],c[x][1]);
     44     }
     45 }
     46 void rotate(int x){
     47     int y=fa[x],z=fa[y],l;
     48     l=(c[y][1]==x);
     49     if(!isroot(y))c[z][c[z][1]==y]=x;
     50     fa[c[x][l^1]]=y;fa[y]=x;fa[x]=z;
     51     c[y][l]=c[x][l^1];c[x][l^1]=y;
     52 }
     53 void splay(int x){
     54     q[++top]=x;
     55     for(int i=x;!isroot(i);i=fa[i])
     56         q[++top]=fa[i];
     57     while(top)pushdown(q[top--]);
     58     while(!isroot(x)){
     59         int y=fa[x],z=fa[y];
     60         if(!isroot(y)){
     61             if(c[y][0]==x^c[z][0]==y)rotate(x);
     62             else rotate(y);
     63         }
     64         rotate(x);
     65     }
     66 }
     67 void access(int x){
     68     for(int t=0;x;t=x,x=fa[x])
     69         splay(x),c[x][1]=t;
     70 }
     71 void makeroot(int x){
     72     access(x);
     73     splay(x);
     74     rev[x]^=1;
     75 }
     76 void link(int x,int y){
     77     makeroot(x);
     78     fa[x]=y;
     79     splay(x);
     80 }
     81 void split(int x,int y){
     82     makeroot(x);
     83     access(y);
     84     splay(y);
     85 }
     86 int getl(int x){
     87     while(c[x][0])x=c[x][0];
     88     return x;
     89 }
     90 char s[10];int x,y;
     91 int main(){
     92     //freopen(FILE".in","r",stdin);
     93     //freopen(FILE".out","w",stdout);
     94     n=readint();m=readint();
     95     while(m--){
     96         scanf("%s",s);x=readint(),y=readint();
     97         if(s[0]=='Q'){
     98             makeroot(x);
     99             access(y);
    100             splay(y);
    101             if(getl(y)==x)printf("Yes
    ");
    102             else printf("No
    ");
    103         }
    104         if(s[0]=='D'){
    105             split(x,y);
    106             c[y][0]=fa[x]=0;
    107         }
    108         if(s[0]=='C'){
    109             link(x,y);
    110         }
    111         
    112     }
    113     return 0;
    114 }
    View Code

    [hnoi2010]弹飞绵羊

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<string>
     6 #include<ctime>
     7 #include<cmath>
     8 #include<set>
     9 #include<map>
    10 #include<queue>
    11 #include<algorithm>
    12 #include<iomanip>
    13 using namespace std;
    14 #define FILE "dealing"
    15 #define up(i,j,n) for(int i=(j);i<=(n);i++)
    16 #define pii pair<int,int>
    17 #define LL int
    18 #define mem(f,g) memset(f,g,sizeof(f))
    19 namespace IO{
    20     char buf[1<<15],*fs,*ft;
    21     int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;}
    22     int read(){
    23         int ch=gc(),f=0,x=0;
    24         while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();}
    25         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();}
    26         return f?-x:x;
    27     }
    28     int readint(){
    29         int ch=getchar(),f=0,x=0;
    30         while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
    31         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    32         return f?-x:x;
    33     }
    34 }using namespace IO;
    35 const int maxn=201000,inf=100000000;
    36 int n,m,top;
    37 int fa[maxn],f[maxn],c[maxn][2],q[maxn],rev[maxn],siz[maxn],v[maxn];
    38 void updata(int x){
    39     siz[x]=1+siz[c[x][0]]+siz[c[x][1]];
    40 }
    41 bool isroot(int x){
    42     return c[fa[x]][1]!=x&&c[fa[x]][0]!=x;
    43 }
    44 void rotate(int x){
    45     int d,y=fa[x],z=fa[y];
    46     d=(c[y][1]==x);
    47     if(!isroot(y))c[z][c[z][1]==y]=x;
    48     fa[x]=z;fa[y]=x;fa[c[x][d^1]]=y;
    49     c[y][d]=c[x][d^1];c[x][d^1]=y;
    50     updata(y);updata(x);
    51 }
    52 void splay(int x){
    53     while(!isroot(x)){
    54         int y=fa[x],z=fa[y];
    55         if(!isroot(y)){
    56             if((c[y][1]==x)^(c[z][1]==y))rotate(y);
    57             else rotate(x);
    58         }
    59         rotate(x);
    60     }
    61 }
    62 void access(int x){
    63     for(int t=0;x;t=x,x=fa[x])splay(x),c[x][1]=t,updata(x);
    64 }
    65 void cut(int x,int y){
    66     access(x);splay(y);c[y][1]=fa[x]=0;updata(y);
    67 }
    68 int x,y,z;
    69 char s;
    70 int main(){
    71     //freopen(FILE".in","r",stdin);
    72     //freopen(FILE".out","w",stdout);
    73     n=read();
    74     up(i,1,n)v[i]=read();
    75     for(int i=n;i>=1;i--)if(v[i]+i<=n)fa[i]=v[i]+i;
    76     m=read();
    77     while(m--){
    78         z=read();x=read()+1;
    79         if(z==1){
    80             access(x);
    81             splay(x);
    82             printf("%d
    ",siz[x]);
    83         }
    84         else{
    85             y=read();
    86             cut(x,v[x]+x);
    87             if(y+x<=n)fa[x]=y+x;
    88             else fa[x]=0;
    89             v[x]=y;
    90         }
    91     }
    92     return 0;
    93 }
    View Code

    上面是这两天写的四道题代码;

    敲了几天的LCT代码,感觉不错,决定写个总结;

    LCT可以动态维护某点到根的某些数据;

    方法:将树剖成一条条链,每条链用一个splay维护,这样查询的时候,顺着链向上以深度为关键字合并splay,这样在最后的splay上就可以查询某些信息;

    首先需要构造一棵splay:

    void updata(int x){
    	//需要维护的信息
    }
    void pushdown(int x){
    	//需要下传的标记
    }
    bool isroot(int x){
    	return c[fa[x]][1]!=x&&c[fa[x]][0]!=x;
    }
    void rotate(int x){
    	int d,y=fa[x],z=fa[y];
    	d=(c[y][1]==x);
    	if(!isroot(y))c[z][c[z][1]==y]=x;
    	fa[x]=z;fa[y]=x;fa[c[x][d^1]]=y;
    	c[y][d]=c[x][d^1];c[x][d^1]=y;
    	updata(y);updata(x);
    }
    void splay(int x){
    	q[++top]=x;
    	for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
    	while(top)pushdown(q[top--]);
    	while(!isroot(x)){
    		int y=fa[x],z=fa[y];
    		if(!isroot(y)){
    			if((c[y][1]==x)^(c[z][1]==y))rotate(y);
    			else rotate(x);
    		}
    		rotate(x);
    	}
    }
    

    操作1:access(LCT的核心操作):

    void access(int x){for(int t=0;x;t=x,x=fa[x])splay(x),c[x][1]=t,updata(x);}
    

    操作2:makeroot(使某个点成为所在树的根,实际是splay翻转):

    void makeroot(int x){access(x);splay(x);rev[x]^=1;}
    

     需要注意的是,有些题目中需要维护的信息与左右子树的位置有关,打rev标机的时候注意;

     这个操作比较方便,但可以不使用;

    操作3:link(连接两棵树):

    void link(int x,int y){makeroot(x);fa[x]=y;splay(x);}
    

     也有其他写法;

    操作4:cut(断开两个树):

    void cut(int x,int y){makeroot(x);access(y);splay(x);c[x][1]=fa[y]=0;}
    

    时间上: 

    LCT的常数大(主要是splay),但很灵活,很多无良出题人喜欢卡LCT;

    树链剖分不能动态维护信息;

  • 相关阅读:
    jquery.cookie中的操作
    tooltip 鼠标移动上去出现图片或文字与title大同小异
    jQuery.Autocomplete实现自动完成功能-搜索提示功能
    C#WinForm中复制、粘贴文本到剪贴板
    SQL索引一步到位
    冒泡排序与选择排序
    插入排序(直接插入、折半、Shell)
    .netLinq动态Where条件
    C#多态
    C#面向对象
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6140862.html
Copyright © 2020-2023  润新知