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