zoukankan      html  css  js  c++  java
  • 数据结构&图论: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
    ",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
    ",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
    ",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
    ",mx[y]);break;
    152             }
    153         }
    154         puts("");
    155     }
    156     return 0;
    157 }
  • 相关阅读:
    oracle_dblink配置
    Data Pump(数据抽取)介绍
    亲测 logminer挖掘
    基础命令
    锁_rac环境kill锁表会话后出现killed状态(解决)
    ASM磁盘组空间不足--ORA-15041:DISGROUP DATA space exhausted (生产库案例)
    where子句的具体含义
    Oracle常用脚本——通过RMAN配置RAC环境的分布式磁带机
    如何创建动态的多维数组且内存空间连续
    Hibernate级联删除
  • 原文地址:https://www.cnblogs.com/aininot260/p/9418709.html
Copyright © 2011-2022 走看看