数据结构&图论: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 }

 

posted @ 2018-08-04 15:15  静听风吟。  阅读(397)  评论(0编辑  收藏  举报