[河南省队2012] 找第k小的数
Posted 鄉勇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[河南省队2012] 找第k小的数相关的知识,希望对你有一定的参考价值。
★★☆ 输入文件:kth.in
输出文件:kth.out
简单对比
时间限制: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;
- 思路:主席树+权值线段树
- 代码实现:
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
以上是关于[河南省队2012] 找第k小的数的主要内容,如果未能解决你的问题,请参考以下文章
COGS 930. [河南省队2012] 找第k小的数 主席树
COGS 1534 [NEERC 2004]K小数 &&COGS 930 [河南省队2012] 找第k小的数 可持久化01Trie