• BZOJ 2733 [HNOI2012]永无乡 (权值线段树启发式合并+并查集)


    题意:

    n<=1e5的图里,在线连边、查询某连通块第k大

    思路:

    练习线段树合并的好题,因为依然记得上一次启发式合并trie的时候内存爆炸的恐怖,所以这次还是用了动态开点、回收

    听说启发式合并splay更快QAQ,学会了试试

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
         
    #define fst first
    #define sc second
    #define pb push_back
    #define mp make_pair
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x))
     
    using namespace std;
     
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
     
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 1e5+100;
    const int maxm = 6e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    int n,m;
    int q;
    int ls[maxn*66],rs[maxn*66],dat[maxn*66];
    int root[maxn];
    int a[maxn],id[maxn];
    
    int f[maxn];
    int find(int x){
        return f[x]==x?x:f[x]=find(f[x]);
    }
    
    int tot;
    queue<int>pool;
    int New(){
        if(!pool.empty()){
            int x = pool.front();
            pool.pop();
            return x;
        }
        ++tot;
        return tot;
    }
    void del(int x){
        if(!x)return;
        pool.push(x);
        return;
    }
    int build(int l, int r, int x){
        int mid = (l+r)>>1;
        int p = New();
        dat[p]=1;
        if(l==r)return p;
        if(x<=mid)ls[p]=build(l,mid,x);
        else rs[p]=build(mid+1,r,x);
        return p;
    }
    int merge(int p, int q){// leave p
        if(!p)return q;
        if(!q)return p;
        ls[p]=merge(ls[p],ls[q]);
        rs[p]=merge(rs[p],rs[q]);
        dat[p]+=dat[q];
        ls[q]=rs[q]=dat[q]=0;
        del(q);
        return p;
    }
    int query(int x, int l, int r, int k){
        int mid = (l+r)>>1;
        if(l==r)return l;
        if(dat[ls[x]]>=k){
            return query(ls[x],l,mid,k);
        }
        else{
            return query(rs[x],mid+1,r,k-dat[ls[x]]);
        }
    }
    int main() {
        scanf("%d %d" ,&n, &m);
        for(int i = 1; i <= n; i++){
            f[i]=i;
            scanf("%d", &a[i]);
            id[a[i]]=i;
            root[i]=build(1,n,a[i]);
        }
        /*for(int i = 1; i <= n; i++){
            printf("-- %d root::%d
    ",i,root[i]);
        }
        for(int i = 1; i <= tot; i++){
            //printf("%d ==== %d %d %d
    ",i,ls[i],rs[i],dat[i]);
        }*/
        for(int i = 1; i <= m; i++){
            int x,y;
            scanf("%d %d" ,&x, &y);
            int t1 = find(x);
            int t2 = find(y);
            if(t1!=t2){
                root[t1]=merge(root[t1],root[t2]);
                f[t2]=t1;
            }
        }
        scanf("%d", &q);
        while(q--){
            char op[5];
            int x,y;
            scanf("%s %d %d", op,&x,&y);
            if(op[0]=='Q'){
                int t = find(x);
                if(dat[root[t]]<y){printf("-1
    ");continue;}
                else printf("%d
    ",id[query(root[t],1,n,y)]);
            }
            else{
                int t1 = find(x);
                int t2 = find(y);
                if(t1!=t2){
                    root[t1]=merge(root[t1],root[t2]);
                    f[t2]=t1;
                }
            }
        }
        return 0;
    }
    /*
    5 1
    4 3 2 5 1
    1 2
    7
    Q 3 2
    Q 2 1
    B 2 3
    B 1 5
    Q 2 1
    Q 2 4
    Q 2 3
     */
  • 相关阅读:
    剑指offer63:数据流中的中位数
    剑指offer62:二叉搜索树的第k个结点,二叉搜索树【左边的元素小于根,右边的元素大于根】
    剑指offer61:序列化二叉树
    关于手机拍摄的图片在处理过程中出现问题的解决方法
    一道逻辑思考题
    鼠标右键无反应解决方法
    六大设计原则
    开源镜像网站
    获取当前文件夹下的文件名称
    wget使用方法
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10977311.html
Copyright © 2020-2023  润新知