[河南省队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

时间: 2024-10-26 20:29:39

[河南省队2012] 找第k小的数的相关文章

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

930. [河南省队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

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

板子题,只是记得负数加fix最方便 #include <cstdio> const int A=19,N=100010; namespace FIFO { char ch,B[1<<20],*S=B,*T=B; #define getc() (S==T&&(T=(S=B)+fread(B,1,1<<20,stdin),S==T)?0:*S++) #define isd(c) (c>='0'&&c<='9') int aa,bb

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

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

主席树裸板子 #include<cstdio> #include<iostream> #include<algorithm> #define MAXN 100005 #define MAX 2000005 using namespace std; int sum[MAX],l[MAX],mid[MAX],r[MAX],a[MAXN],b[MAXN],n,m,sz,size,root[MAXN],cnt; void build(int &x,int z,int y

分治法题目整理分析 找第k小的数/求逆序对数目/派

设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数. 提示:函数int partition(int a[],int left,int right)的功能是根据a[left]~a[right]中的某个元素x(如a[left])对a[left]~a[right]进行划分,划分后的x所在位置的左段全小于等于x,右段全大于等于x,同时利用x所在的位置还可以计算出x是这批数据按升非降序排列的第几个数.因此可以编制int find(int a[],int left,

两个有序数组,找第k小的数//未完

1.题目描述:a,b两个有序数组,找出第k小的数,logk,二分查找,1个小于怎么办? 2.思路: 对于数组A . B , 如果 B[pb] < A[pa] && B[pb] > A[pa - 1], 那么 B[pb] 一定是第 pa + pb + 1  小的数.比如数组A = {1, 8, 10, 20}, B = {5, 9, 22, 110},pa = 2, pb = 1, 这时,(B[pb] = 9) < (A[pa] =10) && (B[pb]

【2012河南省队互测】【COGS930】找第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 样例输入

算法导论:快速找出无序数组中第k小的数

题目描述: 给定一个无序整数数组,返回这个数组中第k小的数. 解析: 最平常的思路是将数组排序,最快的排序是快排,然后返回已排序数组的第k个数,算法时间复杂度为O(nlogn),空间复杂度为O(1).使用快排的思想,但是每次只对patition之后的数组的一半递归,这样可以将时间复杂度将为O(n). 在<算法导论>有详细叙述 这里主要用C++实现,实现思路就是先选取当前数组的第一个数作为"主轴",将后面所有数字分成两部分,前面一部分小于"主轴",后面一部

二分——无序数组快速查找第K小的数

#1133 : 二分·二分查找之k小数 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回里我们知道Nettle在玩<艦これ>,Nettle的镇守府有很多船位,但船位再多也是有限的.Nettle通过捞船又出了一艘稀有的船,但是已有的N(1≤N≤1,000,000)个船位都已经有船了.所以Nettle不得不把其中一艘船拆掉来让位给新的船.Nettle思考了很久,决定随机选择一个k,然后拆掉稀有度第k小的船. 已知每一艘船都有自己的稀有度,Nettle现在把所有