数据结构&图论:LCT
HDU4010
类比静态区间问题->动态区间问题的拓展
我们这里把区间变成树,树上的写改删查问题,最最最常用LCT解决
LCT用来维护动态的森林,对于森林中的每一棵树,用Splay维护。
LCT是把这些Splay关联在一起的数据结构
我们以HDU4010为例子
int n,m,cnt,top; bool rev[maxn]; int mx[maxn],fa[maxn],v[maxn],tag[maxn],last[maxn],q[maxn]; int c[maxn][2]; struct edge{int to,next;}e[maxn<<1];
这里把树存成了图,邻接表表示,对于森林中的每一棵树,用Splay来维护
mx,fa,v,tag,c和Splay相关,q是个栈用来预处理fa还有协助Splay操作(具体问题请参考本站Splay的那篇介绍)
这里树边为双向边,在遍历的时候注意判断
接下来介绍LCT中的一些概念和实现:
void access(int x) { for(int t=0;x;t=x,x=fa[x]) splay(x),c[x][1]=t,update(x); }
这个access的意思是专门开辟一条从根到x的路径,将其作为“重链”,并使用Splay来进行维护
如果x往下是重边,就将其变成轻边,这样这条重链就独立出来了
void makeroot(int x) { access(x);splay(x);rev[x]^=1; }
这个makeroot的意思是把某一个节点变成整个LCT的根,这个操作配合access操作就可以方便地提取LCT任意两点之间的路径了
void link(int x,int y) { makeroot(x);fa[x]=y; }
Link-Cut Tree中的link,这个的意思就是连接两棵LCT
void cut(int x,int y) { makeroot(x);access(y);splay(y); c[y][0]=fa[c[y][0]]=0;update(y); }
这个的意思就是把一棵LCT分离成两棵LCT
还有一个find函数:
int find(int x) { access(x);splay(x); while(c[x][0]) x=c[x][0]; return x; }
作用类似于并查集,用来判断一个点到底在哪棵LCT上面
还有一个操作是把一条路径的点权增大val
void add(int x,int y,int val) { makeroot(x);access(y);splay(y); tag[y]+=val;mx[y]+=val;v[y]+=val; }
最后给出求路径上最值的方法:
makeroot(x);access(y);splay(y);printf("%d\n",mx[y]);
先把x提取到LCT的根,然后打通到y的路径,然后把y伸展到根直接查询mx[y]即可
我们在进行题目所描述的一系列操作的时候,是需要前提的
link操作只能连接两棵不同的LCT,否则树就不是树了
cut操作只能cut在同一棵LCT上否则没有意思
add操作也只能在同一棵LCT上进行
查询也是如此
其实,修改查询的操作都可以原生态地使用LCT的辅助树:Splay来完成
而对于树的动态操作,一定要借助于LCT的函数来完成
最后给出完整的代码:
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int INF=2000000000; 5 const int maxn=300005; 6 int read() 7 { 8 int x=0;char ch=getchar(); 9 while(ch<'0'||ch>'9') ch=getchar(); 10 while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} 11 return x; 12 } 13 int n,m,cnt,top; 14 bool rev[maxn]; 15 int mx[maxn],fa[maxn],v[maxn],tag[maxn],last[maxn],q[maxn]; 16 int c[maxn][2]; 17 struct edge{int to,next;}e[maxn<<1]; 18 void insert(int u,int v) 19 { 20 e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; 21 e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt; 22 } 23 void update(int x) 24 { 25 int l=c[x][0],r=c[x][1]; 26 mx[x]=max(mx[l],mx[r]); 27 mx[x]=max(mx[x],v[x]); 28 } 29 void pushdown(int x) 30 { 31 int l=c[x][0],r=c[x][1]; 32 if(rev[x]) 33 { 34 rev[l]^=1;rev[r]^=1;rev[x]^=1; 35 swap(c[x][0],c[x][1]); 36 } 37 if(tag[x]) 38 { 39 if(l){tag[l]+=tag[x];mx[l]+=tag[x];v[l]+=tag[x];} 40 if(r){tag[r]+=tag[x];mx[r]+=tag[x];v[r]+=tag[x];} 41 tag[x]=0; 42 } 43 } 44 bool isroot(int x) 45 { 46 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 47 } 48 void rotate(int x) 49 { 50 int y=fa[x],z=fa[y],l,r; 51 if(c[y][0]==x)l=0;else l=1;r=l^1; 52 if(!isroot(y)) 53 { 54 if(c[z][0]==y)c[z][0]=x; 55 else c[z][1]=x; 56 } 57 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 58 c[y][l]=c[x][r];c[x][r]=y; 59 update(y);update(x); 60 } 61 void splay(int x) 62 { 63 top=0;q[++top]=x; 64 for(int i=x;!isroot(i);i=fa[i]) 65 q[++top]=fa[i]; 66 while(top)pushdown(q[top--]); 67 while(!isroot(x)) 68 { 69 int y=fa[x],z=fa[y]; 70 if(!isroot(y)) 71 { 72 if(c[y][0]==x^c[z][0]==y)rotate(x); 73 else rotate(y); 74 } 75 rotate(x); 76 } 77 } 78 void access(int x) 79 { 80 for(int t=0;x;t=x,x=fa[x]) 81 splay(x),c[x][1]=t,update(x); 82 } 83 void makeroot(int x) 84 { 85 access(x);splay(x);rev[x]^=1; 86 } 87 void link(int x,int y) 88 { 89 makeroot(x);fa[x]=y; 90 } 91 void cut(int x,int y) 92 { 93 makeroot(x);access(y);splay(y); 94 c[y][0]=fa[c[y][0]]=0;update(y); 95 } 96 int find(int x) 97 { 98 access(x);splay(x); 99 while(c[x][0]) x=c[x][0]; 100 return x; 101 } 102 void add(int x,int y,int val) 103 { 104 makeroot(x);access(y);splay(y); 105 tag[y]+=val;mx[y]+=val;v[y]+=val; 106 } 107 int main() 108 { 109 while(scanf("%d",&n)!=EOF) 110 { 111 for(int i=0;i<=n;i++) 112 last[i]=tag[i]=rev[i]=fa[i]=c[i][0]=c[i][1]=0; 113 mx[0]=-INF;cnt=0; 114 for(int i=1;i<n;i++) 115 { 116 int u=read(),v=read(); 117 insert(u,v); 118 } 119 for(int i=1;i<=n;i++) mx[i]=v[i]=read(); 120 q[++top]=1; 121 for(int k=1;k<=top;k++) 122 { 123 int now=q[k]; 124 for(int i=last[now];i;i=e[i].next) 125 { 126 if(e[i].to!=fa[now]) 127 { 128 fa[e[i].to]=now; 129 q[++top]=e[i].to; 130 } 131 } 132 } 133 m=read(); 134 while(m--) 135 { 136 int opt=read(),x=read(),y=read(),w; 137 switch(opt) 138 { 139 case 1: 140 if(find(x)==find(y)) {puts("-1");break;} 141 link(x,y);break; 142 case 2: 143 if(find(x)!=find(y)||x==y) {puts("-1");break;} 144 cut(x,y);break; 145 case 3: 146 w=x;x=y;y=read(); 147 if(find(x)!=find(y)) {puts("-1");break;} 148 add(x,y,w);break; 149 case 4: 150 if(find(x)!=find(y)){puts("-1");break;} 151 makeroot(x);access(y);splay(y);printf("%d\n",mx[y]);break; 152 } 153 } 154 puts(""); 155 } 156 return 0; 157 }
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int INF=2000000000; 5 const int maxn=300005; 6 int read() 7 { 8 int x=0;char ch=getchar(); 9 while(ch<'0'||ch>'9') ch=getchar(); 10 while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} 11 return x; 12 } 13 int n,m,cnt,top; 14 bool rev[maxn]; 15 int mx[maxn],fa[maxn],v[maxn],tag[maxn],last[maxn],q[maxn]; 16 int c[maxn][2]; 17 struct edge{int to,next;}e[maxn<<1]; 18 void insert(int u,int v) 19 { 20 e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; 21 e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt; 22 } 23 void update(int x) 24 { 25 int l=c[x][0],r=c[x][1]; 26 mx[x]=max(mx[l],mx[r]); 27 mx[x]=max(mx[x],v[x]); 28 } 29 void pushdown(int x) 30 { 31 int l=c[x][0],r=c[x][1]; 32 if(rev[x]) 33 { 34 rev[l]^=1;rev[r]^=1;rev[x]^=1; 35 swap(c[x][0],c[x][1]); 36 } 37 if(tag[x]) 38 { 39 if(l){tag[l]+=tag[x];mx[l]+=tag[x];v[l]+=tag[x];} 40 if(r){tag[r]+=tag[x];mx[r]+=tag[x];v[r]+=tag[x];} 41 tag[x]=0; 42 } 43 } 44 bool isroot(int x) 45 { 46 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 47 } 48 void rotate(int x) 49 { 50 int y=fa[x],z=fa[y],l,r; 51 if(c[y][0]==x)l=0;else l=1;r=l^1; 52 if(!isroot(y)) 53 { 54 if(c[z][0]==y)c[z][0]=x; 55 else c[z][1]=x; 56 } 57 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 58 c[y][l]=c[x][r];c[x][r]=y; 59 update(y);update(x); 60 } 61 void splay(int x) 62 { 63 top=0;q[++top]=x; 64 for(int i=x;!isroot(i);i=fa[i]) 65 q[++top]=fa[i]; 66 while(top)pushdown(q[top--]); 67 while(!isroot(x)) 68 { 69 int y=fa[x],z=fa[y]; 70 if(!isroot(y)) 71 { 72 if(c[y][0]==x^c[z][0]==y)rotate(x); 73 else rotate(y); 74 } 75 rotate(x); 76 } 77 } 78 void access(int x) 79 { 80 for(int t=0;x;t=x,x=fa[x]) 81 splay(x),c[x][1]=t,update(x); 82 } 83 void makeroot(int x) 84 { 85 access(x);splay(x);rev[x]^=1; 86 } 87 void link(int x,int y) 88 { 89 makeroot(x);fa[x]=y; 90 } 91 void cut(int x,int y) 92 { 93 makeroot(x);access(y);splay(y); 94 c[y][0]=fa[c[y][0]]=0;update(y); 95 } 96 int find(int x) 97 { 98 access(x);splay(x); 99 while(c[x][0]) x=c[x][0]; 100 return x; 101 } 102 void add(int x,int y,int val) 103 { 104 makeroot(x);access(y);splay(y); 105 tag[y]+=val;mx[y]+=val;v[y]+=val; 106 } 107 int main() 108 { 109 while(scanf("%d",&n)!=EOF) 110 { 111 for(int i=0;i<=n;i++) 112 last[i]=tag[i]=rev[i]=fa[i]=c[i][0]=c[i][1]=0; 113 mx[0]=-INF;cnt=0; 114 for(int i=1;i<n;i++) 115 { 116 int u=read(),v=read(); 117 insert(u,v); 118 } 119 for(int i=1;i<=n;i++) mx[i]=v[i]=read(); 120 q[++top]=1; 121 for(int k=1;k<=top;k++) 122 { 123 int now=q[k]; 124 for(int i=last[now];i;i=e[i].next) 125 { 126 if(e[i].to!=fa[now]) 127 { 128 fa[e[i].to]=now; 129 q[++top]=e[i].to; 130 } 131 } 132 } 133 m=read(); 134 while(m--) 135 { 136 int opt=read(),x=read(),y=read(),w; 137 switch(opt) 138 { 139 case 1: 140 if(find(x)==find(y)) {puts("-1");break;} 141 link(x,y);break; 142 case 2: 143 if(find(x)!=find(y)||x==y) {puts("-1");break;} 144 cut(x,y);break; 145 case 3: 146 w=x;x=y;y=read(); 147 if(find(x)!=find(y)) {puts("-1");break;} 148 add(x,y,w);break; 149 case 4: 150 if(find(x)!=find(y)){puts("-1");break;} 151 makeroot(x);access(y);splay(y);printf("%d\n",mx[y]);break; 152 } 153 } 154 puts(""); 155 } 156 return 0; 157 }
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int INF=2000000000; 5 const int maxn=300005; 6 int read() 7 { 8 int x=0;char ch=getchar(); 9 while(ch<'0'||ch>'9') ch=getchar(); 10 while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} 11 return x; 12 } 13 int n,m,cnt,top; 14 bool rev[maxn]; 15 int mx[maxn],fa[maxn],v[maxn],tag[maxn],last[maxn],q[maxn]; 16 int c[maxn][2]; 17 struct edge{int to,next;}e[maxn<<1]; 18 void insert(int u,int v) 19 { 20 e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; 21 e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt; 22 } 23 void update(int x) 24 { 25 int l=c[x][0],r=c[x][1]; 26 mx[x]=max(mx[l],mx[r]); 27 mx[x]=max(mx[x],v[x]); 28 } 29 void pushdown(int x) 30 { 31 int l=c[x][0],r=c[x][1]; 32 if(rev[x]) 33 { 34 rev[l]^=1;rev[r]^=1;rev[x]^=1; 35 swap(c[x][0],c[x][1]); 36 } 37 if(tag[x]) 38 { 39 if(l){tag[l]+=tag[x];mx[l]+=tag[x];v[l]+=tag[x];} 40 if(r){tag[r]+=tag[x];mx[r]+=tag[x];v[r]+=tag[x];} 41 tag[x]=0; 42 } 43 } 44 bool isroot(int x) 45 { 46 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 47 } 48 void rotate(int x) 49 { 50 int y=fa[x],z=fa[y],l,r; 51 if(c[y][0]==x)l=0;else l=1;r=l^1; 52 if(!isroot(y)) 53 { 54 if(c[z][0]==y)c[z][0]=x; 55 else c[z][1]=x; 56 } 57 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 58 c[y][l]=c[x][r];c[x][r]=y; 59 update(y);update(x); 60 } 61 void splay(int x) 62 { 63 top=0;q[++top]=x; 64 for(int i=x;!isroot(i);i=fa[i]) 65 q[++top]=fa[i]; 66 while(top)pushdown(q[top--]); 67 while(!isroot(x)) 68 { 69 int y=fa[x],z=fa[y]; 70 if(!isroot(y)) 71 { 72 if(c[y][0]==x^c[z][0]==y)rotate(x); 73 else rotate(y); 74 } 75 rotate(x); 76 } 77 } 78 void access(int x) 79 { 80 for(int t=0;x;t=x,x=fa[x]) 81 splay(x),c[x][1]=t,update(x); 82 } 83 void makeroot(int x) 84 { 85 access(x);splay(x);rev[x]^=1; 86 } 87 void link(int x,int y) 88 { 89 makeroot(x);fa[x]=y; 90 } 91 void cut(int x,int y) 92 { 93 makeroot(x);access(y);splay(y); 94 c[y][0]=fa[c[y][0]]=0;update(y); 95 } 96 int find(int x) 97 { 98 access(x);splay(x); 99 while(c[x][0]) x=c[x][0]; 100 return x; 101 } 102 void add(int x,int y,int val) 103 { 104 makeroot(x);access(y);splay(y); 105 tag[y]+=val;mx[y]+=val;v[y]+=val; 106 } 107 int main() 108 { 109 while(scanf("%d",&n)!=EOF) 110 { 111 for(int i=0;i<=n;i++) 112 last[i]=tag[i]=rev[i]=fa[i]=c[i][0]=c[i][1]=0; 113 mx[0]=-INF;cnt=0; 114 for(int i=1;i<n;i++) 115 { 116 int u=read(),v=read(); 117 insert(u,v); 118 } 119 for(int i=1;i<=n;i++) mx[i]=v[i]=read(); 120 q[++top]=1; 121 for(int k=1;k<=top;k++) 122 { 123 int now=q[k]; 124 for(int i=last[now];i;i=e[i].next) 125 { 126 if(e[i].to!=fa[now]) 127 { 128 fa[e[i].to]=now; 129 q[++top]=e[i].to; 130 } 131 } 132 } 133 m=read(); 134 while(m--) 135 { 136 int opt=read(),x=read(),y=read(),w; 137 switch(opt) 138 { 139 case 1: 140 if(find(x)==find(y)) {puts("-1");break;} 141 link(x,y);break; 142 case 2: 143 if(find(x)!=find(y)||x==y) {puts("-1");break;} 144 cut(x,y);break; 145 case 3: 146 w=x;x=y;y=read(); 147 if(find(x)!=find(y)) {puts("-1");break;} 148 add(x,y,w);break; 149 case 4: 150 if(find(x)!=find(y)){puts("-1");break;} 151 makeroot(x);access(y);splay(y);printf("%d\n",mx[y]);break; 152 } 153 } 154 puts(""); 155 } 156 return 0; 157 }