题目大意就是给你一些数字,问你最多k次操作后某个数字的最多出现次数、最小的能出现该次的数(最大化的出现次数,具有该最大化的出现次数的最小的数字的值),一次操作是给任意一个数加一。
这是一道二分题
二分最大能拿到的数量
问题就在于怎能判断这个数量能不能拿到以及记录此时的最小数字
我就是想不到优化方法才A不了的,但是之后听了大神们的想法后,豁然开朗,就是用一个前缀和。
想知道前缀和解此题原理就自己推演一遍就行了
下面是代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL long long
using namespace std;
const int maxn = 100010;
LL va[maxn],sum[maxn];
int main()
{
LL n,k;
while(~scanf("%lld%lld",&n,&k)){
for(int i=0;i<n;i++) scanf("%lld",&va[i]);
sort(va,va+n);
sum[0] = va[0];
for(int i=1;i<n;i++) sum[i] = sum[i-1] + va[i];
LL l = 0 , r = n, mid;
LL ans1 = 0,ans2 = 0;
while(r >= l){
mid = (l+r)>>1;
bool flag = false;
for(LL i = mid-1;i<n;i++){
LL t;
if(i==mid-1) t = sum[i];
else t = sum[i] - sum[i-mid];
if(t+k >= mid*va[i]){
flag = true;
ans2 = va[i];
break;
}
if(flag) break;
}
if(flag){
l = mid + 1;
ans1 = mid;
}
else r = mid - 1;
//printf("%lld %lld\n",ans1,ans2);
}
printf("%lld %lld\n",ans1,ans2);
}
return 0;
}