在区间多次高效率查询,RMQ算法可完美解决区间最值,如果查询区间第几大或第几小的值,可用划分树或归并树,划分树比归并树要快很多,不过这次给大家贴个我自己写的归并树模板题:
#include<stdio.h>
int seg[20][100001];
void build(int l,int r,int deep)
{
if(l==r)
{
scanf("%d",&seg[deep][l]);
return;
}
int m=(l+r)/2;
build(l,m,deep+1);
build(m+1,r,deep+1);
int i,j,k;
i=k=l,j=m+1;
while(i<=m&&j<=r)
{
if(seg[deep+1][i]<seg[deep+1][j])
seg[deep][k++]=seg[deep+1][i++];
else
seg[deep][k++]=seg[deep+1][j++];
}
while(i<=m)
seg[deep][k++]=seg[deep+1][i++];
while(j<=r)
seg[deep][k++]=seg[deep+1][j++];
}
int counthelp(int L,int R,int deep,int key)
{
int l,r,m;
l=L,r=R;
while(l<=r)
{
m=(l+r)/2;
if(seg[deep][m]<=key)
l=m+1;
else
r=m-1;
}
return l-L;
}
int count(int ql,int qr,int l,int r,int deep,int key)
{
if(l>=ql&&r<=qr)
{
return counthelp(l,r,deep,key);
}
int ans=0;
int m=(l+r)/2;
if(m>=ql)
ans+=count(ql,qr,l,m,deep+1,key);
if(m<qr)
ans+=count(ql,qr,m+1,r,deep+1,key);
return ans;
}
int query(int ql,int qr,int L,int R,int k)
{
int l,r,m;
l=L,r=R;
while(l<=r)
{
m=(l+r)/2;
int temp=count(ql,qr,L,R,1,seg[1][m]);
if(temp<k)
l=m+1;
else
r=m-1;
}
return seg[1][l];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
build(1,n,1);
while(m--)
{
int s,t,k;
scanf("%d%d%d",&s,&t,&k);
printf("%d\n",query(s,t,1,n,k));
}
}
}