zoukankan      html  css  js  c++  java
  • POJ 2104 K-th Number

    题意:
    给n、m,下面有n个数 (编号1到n)
    有m个询问,询问的是上面的数的编号在[left,right]之间第k小的数
    n、m<=105

    题解:
    ①主席树入门模板题
    ②对于这种区间求第k小数,我们的思路就是找到一个数x,使得区间中小于x的数恰好不多于k
    ③于是我们可以对权值建一颗线段树,树的节点储存个数,查询的时候如果左儿子的个数>=k,就递归进左儿子找,否则就去有儿子找
    ④但由于这道题是区间查询,直接像之前那样建树显然只能查询整个序列,所以我们要建立可持久化线段树(主席树)
    ⑤显然一个数的出现次数是满足区间加减的,因此,如果要查询一个数x在区间[left,right]中出现的次数,可以用x在[1,right]中出现的次数-x在[1,left-1]中出现的次数即可
    ⑥于是我们就可以建主席树了
    ⑦查询的时候直接用right处的主席树的权值 - left-1处的主席树的权值即可
    ⑧进阶版:HYSBZ 1901 Dynamic Rankings (带修改主席树)

    友情链接(四倍经验):
    POJ 2761 Feed the dogs
    HDU 2665 Kth number
    51Nod 1175 区间中第K大的数

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=100000+10;
    struct Node{
            int lch,rch;
            int data;
    }a[maxn<<5];
    int n,q,A[maxn];
    int Map[maxn],cnt;
    int root[maxn],num;
    void Init();
    void Build(int&,int,int);
    void Update(int&,int,int,int,int);
    int Query(int,int,int,int,int);
    signed main(){
            Init();
            return 0;
    }
    void Init(){
            num=0;
            scanf("%d%d",&n,&q);
            for(int i=1;i<=n;i++){
                    scanf("%d",&A[i]);
                    Map[i]=A[i];
            }
            sort(Map+1,Map+1+n);
            cnt=unique(Map+1,Map+1+n)-(Map+1);
            Build(root[0],1,cnt);//先将根为0的树建出来(建整个树)
            for(int i=1;i<=n;i++){
                    int x=lower_bound(Map+1,Map+1+cnt,A[i])-Map;
                    Update(root[i],root[i-1],1,cnt,x);
            }//将每个点所影响的新链建出来
            while(q--){
                    int left,right,k;
                    scanf("%d%d%d",&left,&right,&k);
                    int x=Query(root[left-1],root[right],1,cnt,k);
                    //查询区间第k大数(小→大第k个)
                    printf("%d
    ",Map[x]);
            }
    }
    void Build(int &u,int left,int right){
            u=++num;
            a[u].data=0;
            if(left==right)return;
            int mid=(left+right)>>1;
            Build(a[u].lch,left,mid);
            Build(a[u].rch,mid+1,right);
    }
    void Update(int &u,int y,int left,int right,int pos){
            u=++num;
            a[u].lch=a[y].lch;a[u].rch=a[y].rch;
            a[u].data=a[y].data+1;
            if(left==right)return;
            int mid=(left+right)>>1;
            if(pos<=mid)Update(a[u].lch,a[y].lch,left,mid,pos);
            else Update(a[u].rch,a[y].rch,mid+1,right,pos);
    }
    int Query(int u,int v,int left,int right,int k){
            if(left==right)return left;
            int mid=(left+right)>>1;
            int data=a[a[v].lch].data-a[a[u].lch].data;
            if(data>=k)return Query(a[u].lch,a[v].lch,left,mid,k);
            else return Query(a[u].rch,a[v].rch,mid+1,right,k-data);
    }

     

  • 相关阅读:
    NX二次开发-UFUN获取系统相关信息UF_ask_system_info
    NX二次开发-UFUN设置环境变量UF_set_variable
    NX二次开发-UFUN获取环境变量路径,将环境变量转换为字符串,字符串拼接UF_translate_variable
    NX二次开发-UFUN终止UF_terminate
    NX二次开发-UFUN计时函数UF_begin_timer
    NX二次开发-获取WCS标识UF_CSYS_ask_wcs
    NX二次开发-UFUN将工程图转成CGM和PDF文件UF_CGM_export_cgm
    require.js简单入门
    【转】JS中的call()和apply()方法
    C# Enum枚举类型操作扩展类
  • 原文地址:https://www.cnblogs.com/holy-unicorn/p/9510349.html
Copyright © 2011-2022 走看看