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