COGS 930. [河南省队2012] 找第k小的数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了COGS 930. [河南省队2012] 找第k小的数相关的知识,希望对你有一定的参考价值。

题目描述

看到很短的题目会让人心情愉悦,所以给出一个长度为N的序列A1,A2,A3,...,AN,

现在有M个询问,每个询问都是Ai...Aj中第k小的数等于多少。

 

输入格式



第一行两个正整数N,M。

 

第二行N个数,表示序列A1,A2,...,AN。

 

紧着的M行,每行三个正整数i,j,k(k≤j-i+1),表示

 

询问Ai...Aj中第k小的数等于多少。

 

输出格式

 

共输出M行,第i行输出第i个询问的答案。

 

样例输入1:

 

4 3

4 1 2 3

1 3 1

2 4 3

1 4 4

 

样例输出1:

 

1

 

3

 

4



样例输入2:

 

5 5

 

4 2 9 9 10

 

1 3 1

 

2 4 3

 

1 4 4

 

3 5 2

 

2 5 2



样例输出2:

 

2

 

9

 

9

 

9

 

9



注释:

 

询问区间的第k小值并非严格第k小,例如样例2中第4个询问,询问3到5中第2小的数,

 

答案输出9,并不是严格第2小的10。



数据范围:

 

在50%的数据中,1<=N<=10000,1<=M<=10000,A[i]<=100000;

 

在100%的数据中,1<=N<=100000,1<=M<=100000,A[i]<=1000000;
主席树求静态区间k大值模板
#include <algorithm>
#include <cstdio>
#define N 100500
using namespace std;
struct cmt
{
    int l,r,size;
}tr[N*30];
int n,m,rt[N],tot,a[N],b[N],size;
int build(int l,int r)
{
    int now=++tot;
    tr[now].size=0;
    if(l==r) return now;
    int mid=(l+r)>>1;
    tr[now].l=build(l,mid);
    tr[now].r=build(mid+1,r);
    return now;
}
inline int Rank(int x)
{
    return lower_bound(b+1,b+1+size,x)-b;
}
void update(int l,int r,int x,int &y,int t)
{
    y=++tot;
    tr[y].size=tr[x].size+1;
    if(l==r) return;
    tr[y].l=tr[x].l;
    tr[y].r=tr[x].r;
    int mid=(l+r)>>1;
    if(t<=mid) update(l,mid,tr[x].l,tr[y].l,t);
    else update(mid+1,r,tr[x].r,tr[y].r,t);
}
int ask(int l,int r,int lx,int rx,int k)
{
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(tr[tr[rx].l].size-tr[tr[lx].l].size>=k) return ask(l,mid,tr[lx].l,tr[rx].l,k);
    else {k-=tr[tr[rx].l].size-tr[tr[lx].l].size;return ask(mid+1,r,tr[lx].r,tr[rx].r,k);}
}
int Main()
{
    freopen("kth.in","r",stdin);
    freopen("kth.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+1+n);
    size=unique(b+1,b+1+n)-b-1;
    rt[0]=build(1,size);
    for(int i=1;i<=n;++i) update(1,size,rt[i-1],rt[i],Rank(a[i]));
    for(int l,r,k;m--;)
    {
        scanf("%d%d%d",&l,&r,&k);
        printf("%d\n",b[ask(1,size,rt[l-1],rt[r],k)]);
    }
    return 0;
}
int sb=Main();
int main(int argc,char *argv[]) {;}

 

以上是关于COGS 930. [河南省队2012] 找第k小的数的主要内容,如果未能解决你的问题,请参考以下文章

COGS 930. [河南省队2012] 找第k小的数

COGS 1534 [NEERC 2004]K小数 &&COGS 930 [河南省队2012] 找第k小的数 可持久化01Trie

[河南省队2012] 找第k小的数

COGS2608 [河南省队2016]无根树

堆的问题:大堆小堆都能解决LeetCode215 在数组中找第K大的元素

MATLAB中,如何找第K大的值及其所在位置?