就和普通LCT维护MST一样,只不过我们最开始不加边,先离线之后时间倒流。
然后看成加边操作,维护链上最大值的编号,每次比较链上最大值和当前加入的值选择是否更换即可。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include
//#define int long long
using namespace std;
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
const int N=2e5+10;
int cnt,st[N];
int n,m,q,w[N<<1],idx,res[N];
struct edge{int x,y,z;}e[N];
struct query{int op,x,y;}p[N];
struct node{int ch[2],fa,re,mx,id;}t[N];
int cmp(edge a,edge b){return a.z<b.z;}
inline void push_up(int p){
t[p].id=p,t[p].mx=w[p];
if(t[ls(p)].mx>t[p].mx) t[p].id=t[ls(p)].id,t[p].mx=t[ls(p)].mx;
if(t[rs(p)].mx>t[p].mx) t[p].id=t[rs(p)].id,t[p].mx=t[rs(p)].mx;
}
inline void push_re(int p){swap(ls(p),rs(p)); t[p].re^=1;}
inline void push_down(int p){
if(!t[p].re) return;
if(ls(p)) push_re(ls(p)); if(rs(p)) push_re(rs(p)); t[p].re^=1;
}
inline bool isroot(int x){return ls(t[x].fa)!=x&&rs(t[x].fa)!=x;}
inline void rotate(int x){
int y=t[x].fa,z=t[y].fa,k=rs(y)==x,w=t[x].ch[!k];
if(!isroot(y)) t[z].ch[rs(z)==y]=x; t[x].ch[!k]=y; t[y].ch[k]=w;
if(w) t[w].fa=y; t[y].fa=x; t[x].fa=z; push_up(y);
}
inline void splay(int x){
cnt=1; st[cnt]=x; int y=x;
while(!isroot(y)) st[++cnt]=y=t[y].fa;
while(cnt) push_down(st[cnt--]);
while(!isroot(x)){
int y=t[x].fa,z=t[y].fa;
if(!isroot(y)) rotate((ls(y)==x)^(ls(z)==y)?x:y); rotate(x);
}push_up(x);
}
inline void access(int x){
for(int y=0;x;x=t[y=x].fa) splay(x),rs(x)=y,push_up(x);
}
inline void makeroot(int x){
access(x); splay(x); push_re(x);
}
inline void split(int x,int y){
makeroot(x); access(y); splay(y);
}
int find(int x){
access(x); splay(x); while(t[x].ch[0]) push_down(x),x=t[x].ch[0];
splay(x); return x;
}
inline void link(int x,int y){
makeroot(x); t[x].fa=y;
}
inline void cut(int x,int y){
split(x,y); t[x].fa=ls(y)=0;
}
signed main(){
cin>>n>>m>>q; map<pair<int,int>,int> mp,ep; idx=n;
for(int i=1;i<=m;i++){
cin>>e[i].x>>e[i].y>>e[i].z;
if(e[i].x>e[i].y) swap(e[i].x,e[i].y);
ep[{e[i].x,e[i].y}]=e[i].z;
}
sort(e+1,e+1+m,cmp);
for(int i=1;i<=q;i++){
scanf("%d %d %d",&p[i].op,&p[i].x,&p[i].y);
if(p[i].x>p[i].y) swap(p[i].x,p[i].y);
if(p[i].op==2) mp[{p[i].x,p[i].y}]=1;
}
for(int i=1;i<=m;i++){
if(mp[{e[i].x,e[i].y}]) continue;
if(find(e[i].x)==find(e[i].y)) continue;
w[++idx]=e[i].z; link(e[i].x,idx),link(idx,e[i].y);
}
for(int i=q;i>=1;i--){
if(p[i].op==2){
int x=p[i].x,y=p[i].y; w[++idx]=ep[{x,y}];
if(find(x)!=find(y)) link(x,idx),link(idx,y);
else{
split(x,y); int now=t[y].id;
if(t[now].mx<=w[idx]) continue;
splay(now);
t[ls(now)].fa=t[rs(now)].fa=0;
link(x,idx),link(idx,y);
}
}else split(p[i].x,p[i].y),res[i]=w[t[p[i].y].id];
}
for(int i=1;i<=q;i++) if(p[i].op==1) printf("%d\n",res[i]);
return 0;
}