Voting Judges(AtCoder agc041_B)

传送门

题意

现在有 N N N个题目,每个题目有一个初始票数, M M M个评委,每个评委可以为 V V V个不同的题目投票,投票结束之后选择分数前 P P P个的题目加入到题目集中,询问某种投票之后使得加入到题目集的题目数最多;

题解

首先将原数组 ( a [ i ] ) (a[i]) (a[i])进行降序排序,那么答案一定是从第 P P P个位置开始算起。怎么算呢?记一个前缀数组 b [ i ] b[i] b[i]表示从到达当前位置时,前 i i i个位置都投票数变成 a [ P ] a[P] a[P]是花费的总票数。那么从P位置开始枚举,对于每一个票数可以变为 a [ P ] a[P] a[P]的题目进行判断,如果不满足条件就结束。具体判断看代码咯~

AC Code

/*******************************
*   Coder : He Shuo.           *
*   Type : Original Work       *
*******************************/

#include
#include
using namespace std;
typedef long long ll;

const int MAXN = 1e5 + 50;

ll N,M,V,P;
ll a[MAXN],b[MAXN],sum;

int main()
{
     
    scanf("%lld%lld%lld%lld",&N,&M,&V,&P);
    sum = M * V;
    for(int i = 1;i <= N;i ++)scanf("%lld",&a[i]);
	
    ///降序排序
    sort(a + 1,a + 1 + N,greater<ll>());
    ll ans = P;
	///前P-1道题票数拉满
    sum -= (P - 1) * M;
    
    ///对于每一个可以票数变为a[P]的题目做前缀和,表示到当前i位置时前面的票数都变成a[P]花费的总票数;
    for(int i = P;i <= N;i ++)
    {
     
        if(a[i] + M >= a[P])b[i] = b[i - 1] + a[P] - a[i];
        else break;
    }
    for(ll i = P;i <= N;i ++)
    {
     
        if(a[i] + M >= a[P])
        {
     
            ll dis = sum - b[i];///剩下多少票没投出去;
            ll mx = M - (a[P] - a[i]);///到这里还可以共同升多少票;
            dis -= mx * (i - P + 1);///共同升票剩下的票数;
            if(dis <= (N - i) * M)ans = i;///若剩下的票数可以尽数投给后面不相干的题目说明可以实现;
            else break;
        }
    }
    printf("%lld",ans);
    return 0;
}

你可能感兴趣的:(Voting Judges(AtCoder agc041_B))