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\n",mx[y]); 103 else split(x,y),printf("%lld\n",sum[y]); 104 } 105 return 0; 106 }
[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\n",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 }
[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\n"); 102 else printf("No\n"); 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 }
[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\n",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 }
上面是这两天写的四道题代码;
敲了几天的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;
树链剖分不能动态维护信息;