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

★★☆   输入文件:kth.in   输出文件:kth.out   简单对比
时间限制:1 s   内存限制:128 MB

题目描述

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

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

 

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

 

 

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

 

1 4 4

 

 

 

 

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=1e5+10;
 5 int n,k,sz,ts;
 6 int a,b,c;
 7 int s[maxn],hs[maxn],tt[maxn];
 8 struct tree{int s,l,r,mid,lp,rp;}t[maxn<<5];
 9 void build(int l,int r,int k){
10     t[k].l=l,t[k].r=r;
11     t[k].mid=l+r>>1;
12     if(l==r) return;
13     t[k].lp=++ts,t[k].rp=++ts;
14     build(l,t[k].mid,t[k].lp);
15     build(t[k].mid+1,r,t[k].rp);
16 }
17 void put(int l,int r,int k,int nk,int p){
18     t[nk]=(tree){t[k].s+1,t[k].l,t[k].r,t[k].mid};
19     if(l==r) return;
20     if(p<=t[nk].mid){
21         t[nk].lp=++ts,t[nk].rp=t[k].rp;
22         put(l,t[nk].mid,t[k].lp,t[nk].lp,p);
23     }
24     else{
25         t[nk].rp=++ts,t[nk].lp=t[k].lp;
26         put(t[nk].mid+1,r,t[k].rp,t[nk].rp,p);
27     }
28 }
29 int search(int k,int nk,int v){
30     if(t[k].l==t[k].r) return t[k].l;
31     int w=t[t[nk].lp].s-t[t[k].lp].s;
32     if(v<=w) return search(t[k].lp,t[nk].lp,v);
33     else return search(t[k].rp,t[nk].rp,v-w);
34 }
35 int main(){
36     freopen("kth.in","r",stdin);
37     freopen("kth.out","w",stdout);
38     scanf("%d%d",&n,&k);
39     for(int i=1;i<=n;i++){
40         scanf("%d",&s[i]);
41         hs[i]=s[i];
42     }
43     sort(hs+1,hs+n+1);
44     sz=unique(hs+1,hs+n+1)-hs-1;
45     build(1,sz,tt[0]);
46     for(int i=1;i<=n;i++){
47         int pos=lower_bound(hs+1,hs+sz+1,s[i])-hs;
48         tt[i]=++ts;
49         put(1,sz,tt[i-1],tt[i],pos);
50     }
51     for(int i=1;i<=k;i++){
52         scanf("%d%d%d",&a,&b,&c);
53         printf("%d\n",hs[search(tt[a-1],tt[b],c)]);
54     }
55     return 0;
56 }

钦定的板子。

题目来源:COGS

转载于:https://www.cnblogs.com/J-william/p/6639845.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值