题意:
有n个人,m个评委,每个评委可以选
个人,分数前
名可以被选,问可能被选的人数有多少。
思路:
对分数从大到小排个序,可以肯定的是分数较小的被选,那么分数比它大的也肯定被选,所以我们可以二分答案,进行判断。
对于每个
我们肯定
,然后对
和
加
肯定不会影响
与
比较,然后如果还剩余的话,对
进行分配,如果这个数大于
,那肯定不满足,如果小于的话,我们贪心的尽量多的给他分配,即
,若分配完后,还有剩余那肯定不满足。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
using namespace std;
#define ll long long
const int N = 1e5 +5;
ll a[N];
ll b[N];
bool ok(ll x,ll m,ll v,ll p,ll n){
memcpy(b,a,sizeof a);
for(int i = x;i <= n;++i){
if(!v) break;
b[i] += m;
v --;
}
for(int i = 1;i <= p-1;++i){
if(!v) break;
b[i] += m;
v --;
}
ll d = v * m;
if(d == 0){
return b[x] >= b[p];
}
else{
for(int i = p;i < x;++i){
if(b[i] - b[x] > 0) return 0;
ll po = b[x] - b[i];
po = min(po,m);
d -= po;
if(d <= 0) break;
}
if(d > 0) return 0;
return 1;
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ll n,m,v,p;
cin >> n >> m >> v>>p;
for(int i = 1;i <= n;++i){
cin >> a[i];
}
sort(a + 1,a + n + 1,greater<ll>());
int l = p ,r = n;
while(l < r){
int mid = l + r + 1 >> 1;
if(ok(mid,m,v,p,n)) l = mid;
else r = mid - 1;
}
cout<<l;
return 0;
}