• bzoj2733 永无乡 splay树的启发式合并


    https://vjudge.net/problem/HYSBZ-2733

    给一些带权点,有些点是互相连通的,

    然后给出2种操作,在两点间加一条边,或者询问一个点所在的连通块内的第k小值的编号

    并查集辅助+splay的启发式合并就行

    由于结构简单,动态开点线段树合并也可以做

    我写的是splay,由于一个奇怪的bug,我一气之下把之前的核心代码里的我自己写的splay和rotate代码全换成板子了

    #include <bits/stdc++.h>
    #define endl '
    '
    #define ll long long
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    using namespace std;
    const int maxn=1e6+10,maxm=2e6+10;
    const int INF=0x3f3f3f3f;
    int casn,n,m,k;
    vector<int> pre;
    int find(int now) {return pre[now]==now?now:pre[now]=find(pre[now]);}
    vector<int> val;
    class splaytree{public:
    #define nd node[now]
    #define ndl node[node[now].son[0]]
    #define ndr node[node[now].son[1]]
        struct splaynode{
            int son[2],fa,val,size;
            splaynode(){size=1,fa=son[0]=son[1]=0;}
        };
        int cnt,root;
        vector<splaynode> node;
        inline void pushup(int now){nd.size=ndl.size+ndr.size+1;}
        inline void pushdown(int now){}
        inline int wh(int now){return node[nd.fa].son[1]==now;}
        void rotate(int now){
            int fa=nd.fa,gf=node[fa].fa,c=wh(now);
            pushdown(fa);pushdown(now);
            if(gf) node[gf].son[wh(fa)]=now;
            nd.fa=gf;
            node[fa].son[c]=nd.son[c^1];
            node[node[fa].son[c]].fa=fa;nd.son[c^1]=fa;node[fa].fa=now;
            pushup(fa);pushup(now);
        }
        void splay(int now,int dst=0){
            for(;nd.fa!=dst;rotate(now))
                if(node[nd.fa].fa!=dst)rotate(wh(now)==wh(nd.fa)?nd.fa:now);
                if(!dst) root=now;
        }
        void insert(int pos){
            int now=root,fa=0,val=node[pos].val;
            while(now) fa=now,now=val<nd.val?nd.son[0]:nd.son[1];
            now=pos;
            node[fa].son[val>node[fa].val]=now;
            nd.fa=fa;
            splay(now);
        }
        void order(int now){
            int l=nd.son[0],r=nd.son[1];
            nd.son[0]=nd.son[1]=nd.fa=0;
            nd.size=1;
            if(l) order(l);
            insert(now);
            if(r) order(r);
        }
        void merge(int a,int b){
            if(a==b) return ;
            splay(a);splay(b);
            if(node[a].size>node[b].size) swap(a,b);
            pre[a]=b;root=b;
            order(a);
        }
        int kth(int now,int k){
            splay(now);int lsize=0;
            while(now){
                int lsum=lsize+ndl.size;
                if(k<=lsum) now=nd.son[0];
                else if(k==lsum+1) return now;
                else lsize=lsum+1,now=nd.son[1];
            }
            return -1;
        }
        splaytree(int n){
            node.resize(n+7,splaynode());
            rep(i,1,n) node[i].val=val[i];
            node[0].size=0;
            root=0,cnt=0;
        }
    };
    int main() {
        IO;
        int a,b;
        cin>>n>>m;
        val.resize(n+2);
        pre.resize(n+2);
        rep(i,1,n) cin>>val[i],pre[i]=i;
        splaytree tree(n);
        while(m--) {
            cin>>a>>b;
            a=find(a),b=find(b);
            tree.merge(a,b);
        }
        cin>>m;string s;
        while(m--){
            cin>>s>>a>>b;
            if(s=="B") {
    						a=find(a),b=find(b);
                tree.merge(a,b);
            }else{
    						a=find(a);
                cout<<tree.kth(a,b)<<endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    suse linux 下的 altera 软件 安装。
    全国教育网DNS(转)
    Upan量产 金士顿 G3
    备忘一 wget
    Linux IP 设置方法
    Linux 如何 mount 挂载 iso 虚拟光驱
    安卓学习资料总结
    自己实现的一个Android上面TreeView效果
    Android 学习资料推荐
    Android ListView下拉刷新 Demo
  • 原文地址:https://www.cnblogs.com/nervendnig/p/10358664.html
Copyright © 2020-2023  润新知