Atcoder B - Voting Judges(构造 + 二分)

题意:
有n个人,m个评委,每个评委可以选 v v 个人,分数前 p p 名可以被选,问可能被选的人数有多少。
思路:
对分数从大到小排个序,可以肯定的是分数较小的被选,那么分数比它大的也肯定被选,所以我们可以二分答案,进行判断。
对于每个 m i d mid 我们肯定 + m +m ,然后对 1 p 1 1到p-1 p + 1 p+1到 n n m m 肯定不会影响 a [ m i d ] a[mid] a [ p ] a[p] 比较,然后如果还剩余的话,对 p m i d 1 p到mid-1 进行分配,如果这个数大于 a [ m i d ] + m a[mid] + m ,那肯定不满足,如果小于的话,我们贪心的尽量多的给他分配,即 a [ m i d ] + m a [ i ] a[mid]+m-a[i] ,若分配完后,还有剩余那肯定不满足。


#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;


}

发布了589 篇原创文章 · 获赞 31 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_43408238/article/details/104148866