Voting Judges(AtCoder agc041

    科技2024-11-11  4

    传送门

    题意

    现在有 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<cstdio> #include<algorithm> 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; }
    Processed: 0.052, SQL: 8