Description
Input
Output
Sample Input
3 5 3
1
3
5
Sample Output
1
2
3
Data Constraint
Solution
首先我们二分答案 mid ,那么可以发现这个 mid 排序后的位置最右为:
S=∑i=1n⌊midi⌋其实就是将小于等于它的数的个数相加。但是这样复杂度为 O(N log N) ,显然会超时。
于是我们想到这个的经典解法——分块。
由于上式中 ⌊midi⌋ 事实上有很多值是相同的,且值的数量不超过 O(n√) 。
所以我们跳着跳着地一段一段加,每次 i 跳到
⌊mid⌊midi⌋⌋+1 统计时就整个区间统计。时间复杂度 O(n√ log n) 。
Code
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=5001;
int n,m,k;
inline int read()
{
int X=0,w=1; char ch=0;
while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
return X*w;
}
inline int min(int x,int y)
{
return x<y?x:y;
}
inline bool check(int x)
{
long long pos=0;
//for(int i=1;i<=n;i++) pos+=x/i;
for(int i=1,p,mx=min(n,x);i<=mx;i=p+1)
{
p=x/(x/i);
pos+=(long long)(p-i+1)*(x/i);
}
return pos>=k;
}
int main()
{
n=min(read(),read());
int q=read();
while(q--)
{
int l=1,r=k=read(),ans;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid)) ans=mid,r=mid-1; else l=mid+1;
}
printf("%d\n",ans);
}
return 0;
}