zoukankan      html  css  js  c++  java
  • 数据结构训练之一

    https://www.luogu.org/problem/P3224

    题目特性:

    动态维护,询问范围第k大

    能够想到的是并查集权值线段树,但是它是动态维护啊,会加边啊,怎么办?

    权值线段树合并,并查集维护,动态开点保证空间复杂度

    清晰明了的代码

    code:

    #include <cctype>
    #include <cstdio>
    using namespace std;
    const int maxn=1e5+5, maxseg=maxn*20;//动态开点线段树空间是NlogN 
    int n, m, q, v[maxn], id[maxn], fa[maxn];
    int cnt, root[maxn], lc[maxseg], rc[maxseg], seg[maxseg];
    void get(int &x){
        int flag=1; char c;
        for (c=getchar(); !isdigit(c); c=getchar())
            if (c=='-') flag=-1;
        for (x=c-48; c=getchar(), isdigit(c); )
            x=(x<<3)+(x<<1)+c-48; x*=flag;
    }
    int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); }
    void add(int &x, int l, int r, int pos){
        if (!x) x=cnt++;
        if (l==r){ ++seg[x]; return; }
        int mid=(l+r)>>1;
        if (pos>mid) add(rc[x], mid+1, r, pos);
        else add(lc[x], l, mid, pos);
        seg[x]=seg[lc[x]]+seg[rc[x]];
    }
    int merge(int x, int y){
        if (!x) return y; if (!y) return x;
        lc[y]=merge(lc[x], lc[y]);
        rc[y]=merge(rc[x], rc[y]);
        seg[y]=seg[lc[y]]+seg[rc[y]];
        return y;
    }
    int query(int now, int l, int r, int k){
        if (l==r) return l;
        int mid=(l+r)>>1;
        if (seg[lc[now]]>=k) return query(lc[now], l, mid, k);
        else return query(rc[now], mid+1, r, k-seg[lc[now]]);
    }
    int main(){
        get(n); get(m);
        for (int i=1; i<=n; ++i){
            get(v[i]); id[v[i]]=i;
            fa[i]=i; root[i]=cnt++;
            add(root[i], 1, n, v[i]);
        }
        int t1, t2;
        for (int i=0; i<m; ++i){
            get(t1); get(t2);
            merge(root[find(t1)], root[find(t2)]);
            fa[find(t1)]=find(t2);
        }
        get(q); char c; int x, y;
        for (int i=0; i<q; ++i){
            while (!isgraph(c=getchar()));
            get(x); get(y);
            if (c=='Q'){
                x=root[find(x)];
                if (seg[x]<y) puts("-1");
                else printf("%d
    ", id[query(x, 1, n, y)]);
            } else {
                merge(root[find(x)], root[find(y)]);
                fa[find(x)]=find(y);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    php实现一个简单的四则运算计算器
    linux下service+命令和直接去执行命令的区别,怎么自己建立一个service启动
    mongodb
    随笔一个dom节点绑定事件
    php-fpm 启动参数及重要配置详解
    PHP的设计模式之工厂模式
    linux下mysql数据的导出和导入
    windows下mongodb安装与使用图文教程(整理)
    MySQL性能分析及explain的使用
    nginx反向代理缓存服务器的构建
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/11645847.html
Copyright © 2011-2022 走看看