时间限制: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;
}