有一个长度为n的序列n<=1e5
每次把长度大于等于k的区间的第k大的数
放在b数列中,问b数列当中的第m大的数是什么
首先:答案是第m大的数,那么说明b数列中大于
等于该答案的数都是从区间中取出来的,而且取了
m个,而比答案小的数的话,那么大于等于该数的
取出的区间数目会大于m所以可以二分答案,对于当前
答案,算出有多少个区间的第k大的数(这个数还得比
当前二分的答案大),如果大于m说明较小,反之亦然。
#include <iostream>
#include <cstdio>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
using namespace std;
const int maxn=1e5+100;
int p[maxn],n,k;
ll m;
ll compute(int o);
int main()
{
int t,ans,l,r,mid;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%lld",&n,&k,&m);
rep(i,1,n) scanf("%d",&p[i]);
l=1,r=1000000000;
while(l<=r)
{
mid=(l+r)/2;
if(compute(mid)>=m)
l=mid+1,ans=mid;
else
r=mid-1;
}
printf("%d\n",ans);
}
return 0;
}
ll compute(int o)
{
int i,j=1,num=0;
ll s=0;
for(i=1;i<=n;i++)
{
if(p[i]>=o) num++;
if(num==k)
{
while(p[j]<o)
s+=n-i+1,j++;
s+=n-i+1;
j++,num--;
}
}
return s;
}
/*
有一个长度为n的序列n<=1e5
每次把长度大于等于k的区间的第k大的数
放在b数列中,问b数列当中的第m大的数是什么
首先:答案是第m大的数,那么说明b数列中大于
等于该答案的数都是从区间中取出来的,而且取了
m个,而比答案小的数的话,那么大于等于该数的
取出的区间数目会大于m所以可以二分答案,对于当前
答案,算出有多少个区间的第k大的数(这个数还得比
当前二分的答案大),如果大于m说明较小,反之亦然。
*/