CF 1978 D. Elections (*1600) 思维

CF 1978 D. Elections (*1600) 思维

题目链接

题意

\(n\) 个人进行选举,第 \(i\) 个人有 \(a_i\) 个粉丝投票给他,另外有 \(c\) 个人没想好投给谁。他们会投给编号最小的人。投票最多的人将赢得选举(相同票数,编号选的人获胜)。现在你可以将一些候选人排除在外,这些人的粉丝也会投给编号最小的人。考虑每个人如果想要赢得选举,至少需要排除多少个候选人。

思路

最初,\(c\) 票会给 \(1\) 号,然后我们统计一下最大值,显然最大值对应的答案是 \(0\)。对于其他值,我们需要操作,注意到,每次拿出去的选票只能给编号最小的人,所以对于选手 \(i\) ,我们至少要把前 \(i-1\) 个候选人都排除在外。并将所有的选票加到 选手 \(i\) 上,此时,我们只用判断我们是否是剩余的候选人里票数最多的即可。那么我们倒着枚举,维护后缀最大值即可。如果当前选票小于后缀最大值,那么只需要把最大值拿出来加到选手 \(i\) 上即可。

代码

#include<bits/stdc++.h>

using namespace std;

#define ff first
#define ss second
#define pb push_back
#define all(u) u.begin(), u.end()
#define endl '\n'
#define debug(x) cout<<#x<<":"<<x<<endl;

typedef pair<int, int> PII;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10, M = 105;
const int mod = 1e9 + 7;
const int cases = 1;

void Showball(){
   int n,c;
   cin>>n>>c;
   vector<int> a(n+1);
   vector<LL> s(n+1);
   for(int i=1;i<=n;i++) cin>>a[i];
   int maxn=a[1]+c,idx=1;
   s[1]=a[1];
   for(int i=2;i<=n;i++){
      if(a[i]>maxn){
         maxn=a[i];
         idx=i;
      }
      s[i]=s[i-1]+a[i];
   }
   vector<int> ans(n+1);
   if(idx!=n) ans[n]=n-1; 
   maxn=a[n];
   for(int i=n-1;i>=1;i--){
      if(i==idx) {maxn=max(maxn,a[i]);continue;}
      LL cur=s[i]+c;
      if(cur>=maxn) ans[i]=i-1;
      else ans[i]=i;
      maxn=max(maxn,a[i]);
   }
   for(int i=1;i<=n;i++) cout<<ans[i]<<" \n"[i==n];
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T=1;
    if(cases) cin>>T;
    while(T--)
    Showball();
    return 0;
}                 
posted @ 2024-06-21 03:13  Showball  阅读(2)  评论(0编辑  收藏  举报