• 并查集 + splay启发式合并


    并查集 + splay启发式合并 - AcWing 1063 - 永无乡

    本题用并查集维护连通性,用splay支持在线查询第k大。为了使得splay能够完成合并操作,本题需要利用启发式的思想,即每次合并都将节点数少的splay的所有节点加入到节点数较多的splay中去。可以证明,splay的启发式合并的复杂度为(O(nlogn))的。

    // splay 启发式合并
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 500010;
    int n,m,temp;
    struct Node{
        int s[2],p,v,id;
        int size;
        void init(int _v,int _id,int _p){
            v = _v;
            id = _id;
            p = _p;
            size = 1;
        }
    }tr[N];
    
    int root[N],idx;
    
    int f[N];
    int find_f(int a){
        if(f[a]==a)return a;
        else return f[a] = find_f(f[a]);
    }
    
    inline int ws(int x){
        return tr[tr[x].p].s[1] == x;
    }
    
    void push_up(int x){
        tr[x].size = tr[tr[x].s[0]].size + tr[tr[x].s[1]].size + 1;
    }
    
    void rotate(int x){
        int y = tr[x].p;
        int z = tr[y].p;
        int k = ws(x);
        
        // modify z
        tr[z].s[ws(y)] = x;
        
        // modify y
        tr[y].p = x;
        tr[y].s[k] = tr[x].s[k^1];
        
        // modify m
        tr[tr[x].s[k^1]].p = y;
        
        // modify x
        tr[x].p = z;
        tr[x].s[k^1] = y;
        
        push_up(y);
        push_up(x);
    }
    
    void splay(int x,int k,int rt){
        while(tr[x].p != k){
            int y = tr[x].p;
            int z = tr[y].p;
            if(z != k){
                if(ws(x) ^ ws(y)){
                    rotate(x);
                }else{
                    rotate(y);
                }
            }
            rotate(x);
        }
        if(!k) root[rt] = x;
    }
    
    void insert(int v,int id,int rt){
        int u = root[rt], p = 0;
        while(u){
            p = u;
            u = tr[u].s[v > tr[u].v];
        }
        u = ++idx;
        if(p) tr[p].s[v > tr[p].v] = u;
        tr[u].init(v,id,p);
        splay(u,0,rt);
    }
    
    
    int get_k(int k,int rt){
        int u = root[rt];
        while(u){
            if(tr[tr[u].s[0]].size >= k){
                u = tr[u].s[0];
            }else if(tr[tr[u].s[0]].size + 1 == k){
                return tr[u].id;
            }else{
                k -= tr[tr[u].s[0]].size + 1;
                u = tr[u].s[1];
            }
        }
        return -1;
    }
    
    
    void dfs_insert(int node,int rt){
        if(tr[node].s[0]) dfs_insert(tr[node].s[0],rt);
        if(tr[node].s[1]) dfs_insert(tr[node].s[1],rt);
        insert(tr[node].v,tr[node].id,rt);
    }
    
    
    int main(){
        scanf("%d%d",&n,&m);
        // init
        for(int i = 1; i <= n; ++i){
            f[i] = root[i] = i;
            scanf("%d",&temp);
            tr[i].init(temp,i,0);
        }
        idx = n;
        
        // get edges
        while(m--){
            int a,b;
            scanf("%d%d",&a,&b);
            a = find_f(a);
            b = find_f(b);
            if(a != b){
                if(tr[root[a]].size > tr[root[b]].size){
                    swap(a,b);
                }
                dfs_insert(root[a],b);
                f[a] = b;
            }
        }
        
        // op
        scanf("%d",&m);
        
        while(m--){
            char op[2];
            int a,b;
            scanf("%s%d%d",op,&a,&b);
            if(*op == 'B'){
                a = find_f(a);
                b = find_f(b);
                if(a != b){
                    if(tr[root[a]].size > tr[root[b]].size){
                        swap(a,b);
                    }
                    dfs_insert(root[a],b);
                    f[a] = b;
                }
            }else{
                a = find_f(a);
                if(tr[root[a]].size < b) puts("-1");
                else printf("%d
    ",get_k(b,a));
            }
        }
        
        return 0;
    }
    
    
    ---- suffer now and live the rest of your life as a champion ----
  • 相关阅读:
    天下无贼的IT版经典台词(zz)
    matlab混合编程向导(vc,vb,.net...)
    mcc生成的代码加入VC,VC的一些设置
    请问:Win2k下面,怎样取消mediaplayer的预览?
    win2k密码恢复
    **上海铁路局2004年最新时刻发布!**
    VC与Matlab混合编程的快速实现(31)
    校车时刻表
    悼Java师兄(转载)
    制作弹出窗口常用技巧九则
  • 原文地址:https://www.cnblogs.com/popodynasty/p/14402113.html
Copyright © 2020-2023  润新知