• BZOJ 2959 长跑 (LCT+并查集)


    题面:BZOJ传送门

    当成有向边做的发现过不去样例,改成无向边就忘了原来的思路..

    因为成环的点一定都能取到,我们把它们压成一个新点,权值为环上所有点的权值和

    这样保证了图是一颗森林

    每次询问转化为,取出$a$到$b$这条链,求链上所有点的权值和

    这实际是一个不删边的动态维护边双的过程

    可以用$LCT$维护

    加入一条边$<x,y>$时,我们取出链$x,y$

    如果$x,y$原来不连通,把它们连上

    否则说明$x,y$原来就联通的,连上这条边会成环,把$x,y$这条链上的点全都压成一个点,用并查集维护

    每次$access$都在并查集里找父亲就行了

    维护权值的时候细节比较多

      1 #include <vector>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define N1 150010
      6 #define M1 (N1<<1)
      7 #define il inline
      8 #define idx(X) (X-'a')
      9 using namespace std;
     10  
     11 char str[M1];
     12 int n,m,de;
     13 int a[N1],r[N1];
     14  
     15 struct Union{
     16 int fa[N1];
     17 int findfa(int x)
     18 {
     19     int pre,y=x; 
     20     if(!x) return 0;
     21     while(fa[y]!=y) y=fa[y]; 
     22     while(fa[x]!=y){ pre=fa[x]; fa[x]=y; x=pre; }
     23     return y;
     24 }
     25 }U;
     26 struct LCT{
     27 int ch[N1][2],fa[N1],rev[N1],sum[N1],stk[N1],tp;
     28 il int idf(int x){ return (ch[fa[x]][0]==x)?0:1;}
     29 il void pushup(int x){ sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+a[x]; }
     30 il int isroot(int x){ return (ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x)?1:0; }
     31 il void revers(int x){ swap(ch[x][0],ch[x][1]),rev[x]^=1; }
     32 il void pushdown(int x)
     33 { 
     34     if(rev[x])  
     35     {
     36         if(ch[x][0]) revers(ch[x][0]);
     37         if(ch[x][1]) revers(ch[x][1]);
     38         rev[x]^=1;
     39     }
     40 }
     41 il void rot(int x)
     42 {
     43     int y=fa[x],ff=fa[y],px=idf(x),py=idf(y);
     44     if(!isroot(y)) ch[ff][py]=x; fa[x]=ff;
     45     fa[ch[x][px^1]]=y; ch[y][px]=ch[x][px^1];
     46     fa[y]=x; ch[x][px^1]=y;
     47     pushup(y),pushup(x);
     48 }
     49 void splay(int x)
     50 {
     51     int y=x; stk[++tp]=x;
     52     while(!isroot(y)){stk[++tp]=fa[y],y=fa[y];}
     53     while(tp){pushdown(stk[tp--]);}
     54     while(!isroot(x))
     55     {
     56         y=fa[x];
     57         if(isroot(y)) rot(x);
     58         else if(idf(y)==idf(x)) rot(y),rot(x);
     59         else rot(x),rot(x);
     60     }
     61 }
     62 void access(int x)
     63 {
     64     for(int y=0;x;y=x,fa[x]=U.findfa(fa[x]),x=fa[x])
     65         splay(x),ch[x][1]=y,pushup(x);
     66 }
     67 void mkroot(int x)
     68 {
     69     access(x);
     70     splay(x);
     71     revers(x);
     72 }
     73 int findroot(int x)
     74 {
     75     access(x); splay(x);
     76     while(ch[x][0]) pushdown(ch[x][0]),x=ch[x][0];
     77     splay(x); return x;
     78 }
     79 void split(int x,int y)
     80 {
     81     mkroot(x); 
     82     access(y);
     83     splay(y);
     84 }
     85 void dfs(int x,int root)
     86 {
     87     U.fa[x]=root; 
     88     if(ch[x][0]) dfs(ch[x][0],root);
     89     if(ch[x][1]) dfs(ch[x][1],root);
     90 }
     91 int link(int x,int y)
     92 {
     93     /*if(x==4&&y==1)
     94         de=1; */
     95     mkroot(x); access(y); splay(y);
     96     int f=findroot(y);
     97     if(f==x){ //merge
     98         dfs(f,f); a[f]=sum[f];
     99         ch[f][0]=ch[f][1]=0;
    100     }else{ //link
    101         fa[x]=y;
    102     }
    103 }
    104 int query(int x,int y)
    105 {
    106     split(x,y);
    107     if(findroot(y)!=x) return -1;
    108     else return sum[x];
    109 }
    110 }lct;
    111  
    112  
    113 int main()
    114 {
    115     scanf("%d%d",&n,&m);
    116     int i,j,A,B,x,y,v,fl,ans=0,id=0,de;
    117     for(i=1;i<=n;i++) 
    118         scanf("%d",&a[i]), lct.sum[i]=a[i], r[i]=a[i], U.fa[i]=i;
    119     while(m--)
    120     {
    121         scanf("%d%d%d",&fl,&A,&B);
    122         if(fl==1)
    123         { 
    124             x=U.findfa(A); y=U.findfa(B);
    125             lct.link(x,y); 
    126         }
    127         if(fl==2)
    128         { 
    129             x=U.findfa(A); lct.splay(x);
    130             lct.sum[x]+=B-r[A]; 
    131             a[x]+=B-r[A];
    132             r[A]=B;
    133         }
    134         if(fl==3)
    135         {
    136             x=U.findfa(A); y=U.findfa(B);  
    137             printf("%d
    ",lct.query(x,y));
    138         }
    139     }
    140     return 0;
    141 }
  • 相关阅读:
    RSA算法
    本地CodeForces
    基于Giolite 多人开发
    DES算法
    MD5算法
    仓库库存管理系统(C+MySQL+ODBC)
    Spring源码解析(一)开篇
    JDK动态代理实现源码分析
    J.U.C Atomic(一)CAS原理
    JDK 注解详解
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10326209.html
Copyright © 2020-2023  润新知