我的lct比别人慢系列...
因为边双存在欧拉回路,所以每个边双的点只要取一个就可以全取,我们可以把边双缩点,图就变成一棵树了
只有在不同的边双之间连边,缩点才会发生,关键在于怎么缩
我们可以维护一个并查集存每个点在哪个边双里,缩点时就把路径提出来,把并查集全部合并,最后更新一下缩出来的点的全职就好了
因为有了缩点,所以写lct会有微小的变化
主要是access:循环里最后一句要写成把($fa_x$所在点双编号)赋给$x$,因为把边双看作一个点;前面要更新$y$的父亲,因为之前$y$的父亲指向当前点双中的某一个点而不是点双编号$x$
写成这样就ok
void access(int x){ int y=0; while(x){ splay(x); rs=y; if(y)fa[y]=x;//更新fa[y] pushup(x); y=x; x=id.get(fa[x]);//用并查集找fa[x]所在点双的编号 } }
其他就没啥区别了,判连通性用多一个并查集会快很多然而我的代码还是那么慢
寒假都快完了我还没通永EX
#include<stdio.h> void swap(int&a,int&b){a^=b^=a^=b;} struct dsu{ int fa[150010]; int get(int x){return(x==fa[x])?x:(fa[x]=get(fa[x]));} void join(int x,int y){fa[get(x)]=get(y);} }con,id; int ch[150010][2],fa[150010],s[150010],v[150010],r[150010],val[150010]; #define ls ch[x][0] #define rs ch[x][1] void pushup(int x){s[x]=s[ls]+s[rs]+v[x];} void rev(int x){ r[x]^=1; swap(ls,rs); } void pushdown(int x){ if(r[x]){ if(ls)rev(ls); if(rs)rev(rs); r[x]=0; } } void rot(int x){ int y,z,f,b; y=fa[x]; z=fa[y]; f=(ch[y][0]==x); b=ch[x][f]; fa[x]=z; fa[y]=x; if(b)fa[b]=y; ch[x][f]=y; ch[y][f^1]=b; if(ch[z][0]==y)ch[z][0]=x; if(ch[z][1]==y)ch[z][1]=x; pushup(y); pushup(x); } bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} void gao(int x){ if(!isrt(x))gao(fa[x]); pushdown(x); } void splay(int x){ int y,z; gao(x); while(!isrt(x)){ y=fa[x]; z=fa[y]; if(!isrt(y))rot((ch[z][0]==y&&ch[y][0]==x)||(ch[z][1]==y&&ch[y][1]==x)?y:x); rot(x); } } void access(int x){ int y=0; while(x){ splay(x); rs=y; if(y)fa[y]=x; pushup(x); y=x; x=id.get(fa[x]); } } void makert(int x){ access(x); splay(x); rev(x); } void link(int x,int y){ makert(x); fa[x]=y; } void dfs(int rt,int x){ id.fa[x]=rt; if(ls)dfs(rt,ls); if(rs)dfs(rt,rs); ls=rs=0; } void cycle(int x,int y){ makert(x); access(y); splay(y); dfs(y,y); v[y]=s[y]; } void glink(int x,int y){ x=id.get(x); y=id.get(y); if(x==y)return; int f1=con.get(x),f2=con.get(y); if(f1!=f2){ link(x,y); con.join(x,y); }else cycle(x,y); } void add(int x,int d){ x=id.get(x); splay(x); v[x]+=d; s[x]+=d; } int query(int x,int y){ if(con.get(x)!=con.get(y))return-1; x=id.get(x); y=id.get(y); makert(x); access(y); splay(y); return s[y]; } int main(){ int n,m,i,x,y; scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%d",v+i); val[i]=s[i]=v[i]; con.fa[i]=id.fa[i]=i; } while(m--){ scanf("%d%d%d",&i,&x,&y); if(i==1)glink(x,y); if(i==2){ add(x,y-val[x]); val[x]=y; } if(i==3)printf("%d\n",query(x,y)); } }