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;

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

原文地址:https://www.cnblogs.com/chadinblog/p/6140862.html