题目背景
这是个非常经典的主席树入门题——静态区间第K小
数据已经过加强,请使用主席树。同时请注意常数优化
题目描述
如题,给定$N$个正整数构成的序列,将对于指定的闭区间查询其区间内的第$K$小值。
输入输出格式
输入格式:
第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。
第二行包含N个正整数,表示这个序列各项的数字。
接下来M行每行包含三个整数 l, r, kl,r,k , 表示查询区间 [l,r][l,r] 内的第k小值。
输出格式:
输出包含k行,每行1个正整数,依次表示每一次查询的结果
输入输出样例
输入样例#1:
5 5
25957 6405 15770 26287 26465
2 2 1
3 4 1
4 5 1
1 2 2
4 4 1
输出样例#1:
6405
15770
26287
25957
26287
说明
数据范围:
对于20%的数据满足: 1≤N,M≤10
对于50%的数据满足: 1≤N,M≤103
对于80%的数据满足: 1≤N,M≤105
对于100%的数据满足: 1≤N,M≤2⋅105
对于数列中的所有数 a_iai ,均满足 −109≤ai≤109
样例数据说明:
N=5,数列长度为5,数列从第一项开始依次为 [25957,6405, 15770, 26287, 26465 ][25957,6405,15770,26287,26465]
第一次查询为 [2,2][2,2] 区间内的第一小值,即为6405
第二次查询为 [3,4][3,4] 区间内的第一小值,即为15770
第三次查询为 [4,5][4,5] 区间内的第一小值,即为26287
第四次查询为 [1,2][1,2] 区间内的第二小值,即为25957
第五次查询为 [4,4][4,4] 区间内的第一小值,即为26287
题解:最经典的主席树模板题。
#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 200010
int n,m,a[N],b[N],L[N<<5],R[N<<5],T[N],sum[N<<5];
int cnt=0,t,x,y,z;
using namespace std;
inline int read()
{
int f=1,x=0;
char ch=getchar();
if (ch=='-')
{
f=-1;
ch=getchar();
}
while ((ch<'0')||(ch>'9')) ch=getchar();
while ((ch>='0')&&(ch<='9'))
{
x=x*10+ch-48;
ch=getchar();
}
return f*x;
}
inline int build(int l,int r)
{
int root=++cnt;
sum[root]=0;
if (l<r)
{
L[root]=build(l,(l+r)/2);
R[root]=build((l+r)/2+1,r);
}
return root;
}
inline int update(int pre,int l,int r,int p)
{
int root=++cnt;
L[root]=L[pre];
R[root]=R[pre];
sum[root]=sum[pre]+1;
if (l<r)
{
if (p<=(l+r)/2)
L[root]=update(L[pre],l,(l+r)/2,p);
else
R[root]=update(R[pre],(l+r)/2+1,r,p);
}
return root;
}
inline int query(int u,int v,int l,int r,int p)
{
if (l>=r) return l;
int xx=sum[L[v]]-sum[L[u]];
if (xx>=p)
return query(L[u],L[v],l,(l+r)/2,p);
else
return query(R[u],R[v],(l+r)/2+1,r,p-xx);
}
int main()
{
freopen("1.in","r",stdin);
n=read(),m=read();
for (int i=1;i<=n;i++)
{
a[i]=read();
b[i]=a[i];
}
sort(b+1,b+1+n);
t=unique(b+1,b+1+n)-b-1;
T[0]=build(1,t);
for (int i=1;i<=n;i++)
{
int p=lower_bound(b+1,b+t+1,a[i])-b;
T[i]=update(T[i-1],1,t,p);
}
for (int i=1;i<=m;i++)
{
x=read(),y=read(),z=read();
int tt=query(T[x-1],T[y],1,t,z);
printf("%d\n",b[tt]);
}
return 0;
}