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

时间限制:1 s 内存限制:128 MB

题目描述

看到很短的题目会让人心情愉悦,所以给出一个长度为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<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<set>
const int MAXN=100000*20;
using namespace std;
struct Tree{
    int lson,rson,sum;
}tree[MAXN];
int root[MAXN],sz,n,m,from,to,kk,a[MAXN];
vector<int>v;
int id(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
void modify(int x,int &y,int l,int r,int loc){
    tree[++sz]=tree[x];y=sz;tree[y].sum++;
    if(l==r) return;
    int mid=(l+r)>>1;
    tree[y].lson=tree[x].lson;tree[y].rson=tree[x].rson;
    if(loc<=mid) modify(tree[x].lson,tree[y].lson,l,mid,loc);
    else         modify(tree[x].rson,tree[y].rson,mid+1,r,loc);
}
int query(int x,int y,int k,int l,int r){
    if(l==r) return l;
    int mid=(l+r)>>1;
    int t=tree[tree[y].lson].sum-tree[tree[x].lson].sum;
    if(t>=k) query(tree[x].lson,tree[y].lson,k,l,mid);
    else     query(tree[x].rson,tree[y].rson,k-t,mid+1,r);
}
int main(){
    freopen("kth.in","r",stdin);
    freopen("kth.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(register int i=1;i<=n;i++)scanf("%d",&a[i]),v.push_back(a[i]);
    sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());
    for(register int i=1;i<=n;i++) modify(root[i-1],root[i],1,n,id(a[i])); 
    while(m--){
        scanf("%d%d%d",&from,&to,&kk);
        printf("%d\n",v[query(root[from-1],root[to],kk,1,n)-1]);
    }
    return 0;
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值