[WC2006] 水管局长 题解

最大值最小的路径肯定在最小生成树上,考虑用 \(LCT\) 维护最小生成树,只需要维护长度最长的边即可实现。由于 \(LCT\) 维护最小生成树不支持删边,所以采用倒序加边的方式处理。

时间复杂度 \(O(n\log n)\)

#include<bits/stdc++.h>
#define fa(x) lct[x].fa
#define fl(x) lct[x].fl
#define id(x) lct[x].id
#define sn(x,i) lct[x].sn[i]
using namespace std;
const int N=1e5+5,M=1e6+N;
struct node{
    int sn[2],fa,fl,id;
}lct[M];int n,m,q,st[M],u[M],v[M],w[M];
int tp,mp[M],qo[N],qx[N],qy[N],ans[N];
unordered_map<int,int>ma[N];
int check(int x){
    return sn(fa(x),0)!=x&&sn(fa(x),1)!=x;
}int chksn(int x){
    return sn(fa(x),1)==x;
}void push_up(int x){
    id(x)=id(sn(x,(w[id(sn(x,0))]<w[id(sn(x,1))])));
    if(w[x]>w[id(x)]) id(x)=x;
}void push_down(int x){
    if(!x||!fl(x)) return;
    fl(sn(x,0))^=1,fl(sn(x,1))^=1;
    swap(sn(x,0),sn(x,1)),fl(x)=0;
}void rotate(int x){
    int y=fa(x),z=fa(y),k=chksn(x);
    if(!check(y))
        sn(z,chksn(y))=x;
    fa(x)=z,fa(y)=x,fa(sn(x,1-k))=y;
    sn(y,k)=sn(x,1-k),sn(x,1-k)=y;
    push_up(y);
}void splay(int x){
    st[tp=1]=x;
    for(int i=x;!check(i);i=fa(i)) st[++tp]=fa(i);
    while(tp) push_down(st[tp--]);
    while(!check(x)){
        int y=fa(x),z=fa(y);
        if(!check(y))
            rotate(chksn(x)!=chksn(y)?x:y);
        rotate(x);
    }push_up(x);
}void access(int x){
    for(int i=0;x;i=x,x=fa(x))
        splay(x),sn(x,1)=i,push_up(x);
}void mk(int x){
    access(x),splay(x),fl(x)^=1;
}void split(int x,int y){
    mk(x),access(y),splay(y);
}void cut(int x,int y){
    split(x,y),sn(y,0)=fa(x)=0;
}void link(int x,int y){
    mk(x),access(y),fa(x)=y;
}int find(int x){
    access(x),splay(x);
    while(sn(x,0)) x=sn(x,0);
    return x;
}void add(int x){
    if(find(u[x]+m)!=find(v[x]+m))
        return link(u[x]+m,x),link(x,v[x]+m);
    split(u[x]+m,v[x]+m);int idx=id(v[x]+m);
    if(w[idx]<=w[x]) return;
    cut(u[idx]+m,idx),cut(idx,v[idx]+m);
    link(u[x]+m,x),link(x,v[x]+m);
}int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>m>>q;
    for(int i=1;i<=m;i++){
        cin>>u[i]>>v[i]>>w[i];
        ma[u[i]][v[i]]=ma[v[i]][u[i]]=i;
    }for(int i=1;i<=q;i++){
        cin>>qo[i]>>qx[i]>>qy[i];
        if(qo[i]==2) mp[ma[qx[i]][qy[i]]]=1;
    }for(int i=1;i<=m;i++) if(!mp[i]) add(i);
    for(int i=q;i;i--){
        if(qo[i]==1){
            split(qx[i]+m,qy[i]+m);
            ans[i]=w[id(qy[i]+m)];
        }else add(ma[qx[i]][qy[i]]);
    }for(int i=1;i<=q;i++)
        if(ans[i]) cout<<ans[i]<<"\n";
    return 0;
}
posted @   长安一片月_22  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示