我的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));
}
}