zoukankan      html  css  js  c++  java
  • caioj1441:第k小的数Ⅰ

    【传送门:caioj1441


    简要题意:

      给出一个n个数的序列,m个询问,每个询问输入l,r,k,输出第l个数到第r个数第k小的数


    题解:

      首先想到线段树,但是做不到询问区间的第几小,只能做到最大或最小或和

      所以我们用权值线段树——主席树来解决这道题


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct node
    {
        int lc,rc,c;//c维护的是这个区间维护了多少个节点
    }tr[2100000];int len;
    int n,m;
    int a[110000],s[110000],root[110000];
    int LS(int d)
    {
        int l=1,r=n,ans=0;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(s[mid]<=d)
            {
                ans=mid;
                l=mid+1;
            }
            else r=mid-1;
        }
        return ans;
    }
    void Link(int &u,int l,int r,int p)
    {
        if(u==0) u=++len;
        tr[u].c++;
        if(l==r) return ;
        int mid=(l+r)/2;
        if(p<=mid) Link(tr[u].lc,l,mid,p);
        else Link(tr[u].rc,mid+1,r,p);
    }
    void Merge(int &u1,int u2)
    {
        if(u1==0){u1=u2;return ;}
        if(u2==0) return ;
        tr[u1].c+=tr[u2].c;
        Merge(tr[u1].lc,tr[u2].lc);
        Merge(tr[u1].rc,tr[u2].rc);
    }
    int Calc(int u1,int u2,int l,int r,int k)
    {
        if(l==r) return s[l];
        int c=tr[tr[u1].lc].c-tr[tr[u2].lc].c;//用u1这棵线段树减u2这棵线段树就可以得到u1到u2这段区间的信息
        int mid=(l+r)/2;
        if(k<=c) return Calc(tr[u1].lc,tr[u2].lc,l,mid,k);
        else return Calc(tr[u1].rc,tr[u2].rc,mid+1,r,k-c);
    }
    int main()
    {
        len=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            s[i]=a[i];
        }
        sort(s+1,s+n+1);
        memset(root,0,sizeof(root));
        for(int i=1;i<=n;i++)
        {
            Link(root[i],1,n,LS(a[i]));//每次插入以rt[i]为根一条链这条链维护i这个点的信息
            Merge(root[i],root[i-1]);//将其与前i-1条链合并,这样rt[i]为根的这条链维护的就是1~i的信息
        }
        for(int i=1;i<=m;i++)
        {
            int x,y,k;
            scanf("%d%d%d",&x,&y,&k);
            printf("%d
    ",Calc(root[y],root[x-1],1,n,k));
        }
        return 0;
    }
  • 相关阅读:
    mysql慢查询日志功能的使用
    回顾JavsScript对象的克隆
    JavaScript的几种继承方式
    再谈JavaScript中的闭包
    重温JavaScript预编译的四个步骤
    PHP常用设计模式
    编译 php-memcache 扩展时提示Cannot find autoconf
    CentOS 7 下编译安装lnmp之PHP篇详解
    CentOS 7 下编译安装lnmp之MySQL篇详解
    MySQL的转义符 ` 作用
  • 原文地址:https://www.cnblogs.com/Never-mind/p/7709641.html
Copyright © 2011-2022 走看看