zoukankan      html  css  js  c++  java
  • POJ2985 并查集+线段树 求第k大的数

    其实这题之前做过,线段树一直不熟,所以也一直没有搞懂

    本题的关键是线段树原始区间代表的是每一种容器(size不同)的数量

    比如 刚开始都是互不相关的,所以1的容器有n个 2 3 4。。。为0个

    线段树每个结点的附加信息是该区间的和

    本题查找出的代码是关键 比如左右子树分别为sum 27 25 ,则第26大的容器必然在左子树上,继续递归下去,则要在该左子树找 (26-25)大的容器。。。

    通俗讲 本题就是改变点修改 求和变化(附加信息)的情况 只是用k大转化了一下

    线段树还是做的太少,近期还要加强专门训练

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <stack>
    #include <string>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <ctime>
    
    using namespace std;
    
    //#define EdsonLin
    
    #ifdef EdsonLin
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    #else
    #define debug(...)
    #endif //EdsonLin
    
    typedef long long ll;
    typedef double db;
    const int inf = 0x3f3f3f;
    const int MAXN = 2e5+10;
    const int MAXNN = 2e6+100;
    //const int MAXM = 1e6;
    //const int MAXM = 3e4+100;
    const int MOD = 1000000007;
    const db eps = 1e-3;
    #define PB push_back
    
    int a[MAXN],p[MAXN];
    int n,m,k;
    int readint(){int x;scanf("%d",&x);return x;}
    int Find(int x){return (x==p[x]?x:Find(p[x]));}
    void Union(int u,int v){p[u] = Find(u);p[v] = Find(v);p[p[v]] = p[u];}
    void init(){
        for(int i=1;i<=n;i++){
            a[i] = 1;
            p[i] = i;
        }
    }
    
    struct sT{
        int sum[MAXN*3];
        int n;
        void popup(int o){
            int lc = o*2;
            int rc = o*2|1;
            sum[o] = sum[lc] + sum[rc];
        }
        void build(int o,int lc,int rc){
            if(lc==1)sum[o] = n;
            else sum[o] = 0;
            if(lc==rc)return;
            if(lc<rc){
                int mc = lc + (rc-lc)/2;
                build(o*2,lc,mc);
                build(o*2|1,mc+1,rc);
            }
        }
        void update(int o,int lc,int rc,int val,int c){
            int mc = lc + (rc-lc)/2;
            if(lc==rc&&lc==val){sum[o] += c;return;}
            if(lc==rc)return;
            if(mc<val)update(o*2|1,mc+1,rc,val,c);  //此步容易错误 改变所有和val有关节点的信息
            else update(o*2,lc,mc,val,c);
            popup(o);   //向上递归,改变父节点附加信息
        }
        void query(int o,int lc,int rc,int k){
            if(lc==rc){
                printf("%d
    ",lc);
                return;
            }
            int mc = lc+(rc-lc)/2;
            if(k<=sum[o*2|1])query(o*2|1,mc+1,rc,k);
            else query(o*2,lc,mc,k-sum[o*2|1]);
        }
        void init(){
            memset(sum,0,sizeof(sum));
            this->n = n;
        };
    }solver;
    
    
    int main()
    {
        while(cin>>n>>m){
            init();
            solver.init();
            solver.build(1,1,n);
            for(int i=0;i<m;i++){
                int sg;
                scanf("%d",&sg);
                if(!sg){
                    int u,v;
                    scanf("%d%d",&u,&v);
                    u = Find(u);
                    v = Find(v);
                    if(u==v)continue;
                    /*Union(u,v);*/
                    p[v] = u;
                    solver.update(1,1,n,a[u],-1);
                    solver.update(1,1,n,a[v],-1);
                    solver.update(1,1,n,a[u]+a[v],1);
                    a[u] += a[v];
                }else{
                    scanf("%d",&k);
                    solver.query(1,1,n,k);
                }
            }
        }
        //cout << "Hello world!" << endl;
        return 0;
    }
    View Code
    在一个谎言的国度,沉默就是英雄
  • 相关阅读:
    转:Oracle中的日期和字符串互相转换
    jQuery DateTimePicker 日期和时间插件
    js转换时间戳-转换成 yyyy-MM-dd HH:mm:ss
    linux下载服务器上的文件命令-sz
    eclipse中集成maven
    maven的安装和环境配置
    eclipse复制粘贴变卡的解决办法
    在表单提交之前做校验-利用jQuery的submit方法
    centos7 ipaddr 无法查看虚拟机IP解决办法
    linux下tomcat启动很慢的解决办法
  • 原文地址:https://www.cnblogs.com/EdsonLin/p/5643775.html
Copyright © 2011-2022 走看看