現在有 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]的題目進行判斷,如果不滿足條件就結束。具體判斷看程式碼咯~
/*******************************
* 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;
}