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\n",lct.query(x,y)); 138 } 139 } 140 return 0; 141 }