树状数组 cf 602 D

https://codeforces.com/contest/1262/problem/D2
https://blog.csdn.net/A_Bright_CH/article/details/79979559

在树状数组种求第k大的数

#include <stdio.h>
#include <algorithm>
using namespace std;
struct node
{
    int v,id;
    bool operator<(const node &x)const{
        return v==x.v?id<x.id:v>x.v;
    }
}a[200005];
struct data
{
    int k,pos,id;
    bool operator<(const data &x)const{
        return k<x.k;
    }
}q[200005];
int n,c[200005],ans[200005],last[200005];
void add(int x){for(;x<=n;x+=x&(-x))c[x]+=1;}
int query(int k)
{
    int cur=0;
    for(int i=19;i>=0;i--) //为什么要逆序,这样相加才能正好走到第k-1大的位置
    {
        if((1<<i)+cur>n||c[cur+(1<<i)]>=k)continue;
        cur+=1<<i;k-=c[cur]; //这过程是走到第k-1大的过程
    }                        //第8大就是 4+2+1,因为c[8]可能大于k这样子如果 
    return cur+1;            //去掉==的话,即return cur,我们就会返回k-1大的数 
}                            //而!=k,这样我们得到无限逼近k大的数,+1即是第k大 
int main()
{
    int m,tim=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)           //输入的序列 
    {
        scanf("%d",&a[i].v);
        last[i]=a[i].v;
        a[i].id=i;
    }
    sort(a+1,a+1+n);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)           //前k大,并且字典序最小,的第pos个数的值 
    {
        scanf("%d %d",&q[i].k,&q[i].pos);
        q[i].id=i;
    }
    sort(q+1,q+1+m);               //按k的个数排序 
    for(int i=1;i<=m;i++)
    {
        while(tim<q[i].k)tim++,add(a[tim].id);
        ans[q[i].id]=last[query(q[i].pos)];
    }
    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
}
发布了88 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44879687/article/details/103279450