BZOJ2594: [Wc2006]水管局长数据加强版

题意

动态维护最小生成树上最大边

题解

这题有点恶心,还要写一个hash

因为最小生成树具有环切性质,所以LCT维护一下就可以了

代码

#include
#include
#include
#include
#include
#include
#define L(i) (T[i].s[0])
#define R(i) (T[i].s[1])
#define F(i) (T[i].fa)
#define mx(i) (T[i].mx)
#define Loc(i) (R(F(i))==i)
#define W(i) (T[i].w)
#define For(i,j,k) for(int i=(j);i<=(int)k;i++)
#define Forr(i,j,k) for(int i=(j);i>=(int)k;i--)
#define Set(a,b) memset(a,b,sizeof(b))
#define Rep(i,u) for(int i=Begin[u],v=to[i];i;i=Next[i],v=to[i])
#define ll long long 
using namespace std;
const int N=100010,INF=0x3f3f3f3f,M=1000010;
inline void read(int &x){
    x=0;int f(0);char c=getchar();
    while(c<'0'||c>'9')f|=(c=='-'),c=getchar();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    if(f)x=-x;
}

struct edge{
    int u,v,w,mk,id;
}E[M];
inline bool cmp1(edge a,edge b){
    return a.winline bool cmp2(edge a,edge b){
    return a.idstruct node{
    int s[2],w,mx,fa,rev;
};
struct LCT{
    node T[M+N];        
    inline void init(){Set(T,0);}
    inline void pushup(int x){
        mx(x)=x;
        if(L(x)&&W(mx(L(x)))>W(mx(x)))mx(x)=mx(L(x));
        if(R(x)&&W(mx(R(x)))>W(mx(x)))mx(x)=mx(R(x));
    }
    inline void pushdown(int x){
        if(T[x].rev){
            T[x].rev^=1,T[L(x)].rev^=1,T[R(x)].rev^=1;
            swap(L(x),R(x));
        }
    }
    inline bool isrt(int x){
        return R(F(x))!=x&&L(F(x))!=x;
    }
    inline void Pushdown(int x){
        if(!isrt(x))Pushdown(F(x));
        pushdown(x);
    }
    inline void Rotate(int x){
        int A=F(x),B=F(A),l=Loc(x),r=l^1,d=Loc(A);
        if(!isrt(A))T[B].s[d]=x;F(x)=B;
        F(A)=x,F(T[x].s[r])=A,T[A].s[l]=T[x].s[r],T[x].s[r]=A;
        pushup(A);
    }
    inline void splay(int x){
        Pushdown(x);
        while(!isrt(x)){
            if(!isrt(F(x)))Rotate(x);
            Rotate(x);
        }
        pushup(x);
    }
    inline void access(int x){
        for(int i=0;x;i=x,x=F(x))splay(x),R(x)=i,pushup(x);
    }
    inline void reverse(int x){
        access(x);
        splay(x);
        T[x].rev^=1;
    }
    inline int findrt(int x){
        access(x),splay(x);
        while(L(x))x=L(x);
        return x;
    }
    inline void link(int x,int y){
        reverse(x),F(x)=y;
    }
    inline void cut(int x,int y){
        reverse(x),access(y),splay(y);
        L(y)=F(x)=0;pushup(y);
    }
    inline int query(int x,int y){
        reverse(x),access(y),splay(y);
        return mx(y);
    }
    inline void modify(int x,int y,int num,int n){
        int e=query(x,y);
        if(W(e)return;
        cut(e,E[e-n].u);
        cut(e,E[e-n].v);
        link(x,num);
        link(num,y);
    }
}t;
struct ufs{
    int f[N];
    int Find(int x){return f[x]==x?x:f[x]=Find(f[x]);}
    inline void init(int n){For(i,1,n)f[i]=i;}
    inline bool Union(int x,int y){
        int a=Find(x),b=Find(y);
        if(a==b)return 0;
        f[a]=b;
        return 1;
    }
}s;
inline void Kruskal(int n,int m){
    int tot=0;
    s.init(n);
    sort(E+1,E+m+1,cmp1);
    For(i,1,m)
        if(tot1&&!E[i].mk&&s.Union(E[i].u,E[i].v))
            t.link(E[i].u,E[i].id+n),t.link(E[i].id+n,E[i].v),++tot;            
    sort(E+1,E+m+1,cmp2);
}
edge oper[N];
int ans[N],n,m,q;
const int Mod=1000037;
struct Hash{
    ll Begin[Mod+10],Next[Mod+10],to[Mod+10],w[Mod+10][2],e;
    Hash(){
        Set(Begin,0),e=0;
    }
    inline void add(ll key,ll val,ll x,ll y){
        to[++e]=val,Next[e]=Begin[key],Begin[key]=e;w[e][0]=x,w[e][1]=y;
    }
    inline void insert(ll x,ll y,ll val){
        if(x>y)swap(x,y);
        ll key=(x-1)*n+y;
        key%=Mod;
        add(key,val,x,y);
    }
    inline ll find(ll x,ll y){
        if(x>y)swap(x,y);
        ll key=(x-1)*n+y;
        key%=Mod;
        Rep(i,key)
            if(w[i][0]==x&&w[i][1]==y)
                return v;
    }
}H;
int main(){
    read(n),read(m),read(q);
    For(i,1,m)read(E[i].u),read(E[i].v),read(E[i].w),
        H.insert(E[i].u,E[i].v,(E[i].id=i)),t.T[n+i].w=E[i].w,t.pushup(n+i);
    For(i,1,q){
        read(oper[i].mk),read(oper[i].u),read(oper[i].v);
        if(oper[i].mk==2)oper[i].w=H.find(oper[i].u,oper[i].v);
        if(oper[i].mk==2)E[oper[i].w].mk=1;
    }
    Kruskal(n,m);
    Forr(i,q,1){
        if(oper[i].mk==2)t.modify(oper[i].u,oper[i].v,oper[i].w+n,n);
        else {
            int k=t.query(oper[i].u,oper[i].v)-n;
            ans[i]=E[k].w;
        }
    }   
    For(i,1,q)
        if(oper[i].mk==1)
            printf("%d\n",ans[i]);
    return 0;
}

你可能感兴趣的:(最小生成树,动态树,bzoj)