bzoj2959:実行中の長距離(LCT +互いに素セット)

ポータル
思考:有向エッジとタイトルの役に立ちません。
直接図の全体デュアルコンポーネントリンクにメンテナンス情報。
使用 リットル C トン LCT は、それぞれ2つの互いに素セットポイント、およびメンテナンス情報ブロックダブルユニコム。
コード:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
    static char buf[rlen],*ib,*ob;
    (ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
    return ib==ob?-1:*ib++;
}
inline int read(){
    int ans=0;
    char ch=gc();
    while(!isdigit(ch))ch=gc();
    while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
    return ans;
}
const int N=150005;
int n,m,a[N],bcc[N],anc[N];
inline int Find(const int&x){return x^bcc[x]?bcc[x]=Find(bcc[x]):x;}
inline int find(const int&x){return x^anc[x]?anc[x]=find(anc[x]):x;}
typedef long long ll;
namespace lct{
    int son[N][2],siz[N],fa[N];
    ll sum[N],val[N];
    bool rev[N];
    inline bool which(const int&x){return x==son[Find(fa[x])][1];}
    inline bool isroot(const int&x){return !fa[x]||(x!=son[Find(fa[x])][0]&&x!=son[Find(fa[x])][1]);}
    inline void pushup(int p){siz[p]=siz[son[p][0]]+1+siz[son[p][1]],sum[p]=sum[son[p][0]]+val[p]+sum[son[p][1]];}
    inline void pushnow(int p){rev[p]^=1,swap(son[p][0],son[p][1]);}
    inline void pushdown(int p){
        if(!rev[p])return;
        rev[p]^=1;
        if(son[p][0])pushnow(son[p][0]);
        if(son[p][1])pushnow(son[p][1]);
    }
    inline void rotate(int x){
        int y=Find(fa[x]),z=Find(fa[y]),t=which(x);
        if(z&&!isroot(y))son[z][which(y)]=x;
        fa[x]=z,fa[y]=x,son[y][t]=son[x][t^1],son[x][t^1]=y;
        if(son[y][t])fa[son[y][t]]=y;
        pushup(y),pushup(x);
    }
    inline void splay(int x){
        static int stk[N],top;
        stk[top=1]=x;
        for(ri i=x;!isroot(i);i=Find(fa[i]))stk[++top]=Find(fa[i]);
        while(top)pushdown(stk[top--]);
        while(!isroot(x)){
            if(!isroot(Find(fa[x])))rotate(which(x)^which(Find(fa[x]))?x:Find(fa[x]));
            rotate(x);
        }
    }
    inline void access(int x){for(ri y=0;x;y=x,x=Find(fa[y]))splay(x),son[x][1]=y,pushup(x);}
    inline void makeroot(int x){access(x),splay(x),pushnow(x);}
    inline void dfs(int x,int rt){
        bcc[x]=rt;
        pushdown(x);
        if(son[x][0])dfs(son[x][0],rt);
        if(son[x][1])dfs(son[x][1],rt);
    }
    inline void link(int x,int y){makeroot(x),fa[x]=y;}
    inline void cut(int x,int y){makeroot(x),access(y),splay(y),fa[x]=son[y][0]=0,pushup(y);}
    inline void split(int x,int y){makeroot(x),access(y),splay(y);}
}
inline void link(int x,int y){anc[find(x)]=find(y),lct::link(x,y);}
inline void merge(int x,int y){
    lct::split(x,y);
    lct::val[y]=lct::sum[y];
    lct::dfs(y,y);
}
inline void update(int x,int y){
    int fx=Find(x);
    lct::splay(fx);
    lct::val[fx]-=a[x],a[x]=y,lct::val[fx]+=a[x];
    lct::pushup(fx);
}
inline void solve(int x,int y){
    if(find(x)^find(y))puts("-1");
    else if(x==y)cout<<lct::val[x]<<'\n';
    else lct::split(x,y),cout<<lct::sum[y]<<'\n';
}
int main(){
    n=read(),m=read();
    for(ri i=1;i<=n;++i)anc[i]=bcc[i]=i,a[i]=lct::sum[i]=lct::val[i]=read(),lct::siz[i]=1;
    for(ri op,u,v;m;--m){
        op=read(),u=read(),v=read();
        switch(op){
            case 1:{
                u=Find(u),v=Find(v);
                if(u^v){
                    if(find(u)^find(v))link(u,v);
                    else merge(u,v);
                }
                break;
            }
            case 2:{update(u,v);break;}
            case 3:{solve(Find(u),Find(v));break;}
        }
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/dreaming__ldx/article/details/93754360