版权声明:欢迎大家指正错误,有不同观点的欢迎评论,共同进步 https://blog.csdn.net/Sirius_han/article/details/81711252
A. Elections
题意:现有民主投票,已知每张投票的价值以及获得该投票的选手编号,当1号获得的投票数大于其他任何一个选手的获票数是,1号赢,现在1号可以花费相应的价值获得相应的投票,问1号选手的最少花费;
思路:
一:首先直接暴力枚举获票数;
二:三分枚举获票数;
暴力:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> vec[3100], t;
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i=0; i<n; i++){
int p;
ll c;
scanf("%d%lld", &p, &c);
vec[p].push_back(c);
}
for(int i=1; i<=m; i++) sort(vec[i].begin(), vec[i].end(), greater<ll>() );
ll ans=1LL<<60, temp;
for(int i=1; i<=n; i++){
temp=0;
t.clear();
int cnt=vec[1].size();
for(int j=2; j<=m; j++){
int k;
for(k=0; k<i-1&&k<vec[j].size(); k++) t.push_back(vec[j][k]);
for(k; k<vec[j].size(); k++) temp+=vec[j][k], cnt++;
}
sort(t.begin(), t.end());
for(int j=0; j<t.size()&&cnt<i; j++){
temp+=t[j];
cnt++;
}
ans=min(ans, temp);
t.clear();
}
printf("%lld\n", ans);
return 0;
}
三分方法:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> vec[3010], t;
int n, m;
ll cal(int x){
t.clear();
ll temp=0;
int cnt=vec[1].size();
for(int i=2; i<=m; i++){
int k;
for(k=0; k<x-1&&k<vec[i].size(); k++) t.push_back(vec[i][k]);
for(k; k<vec[i].size(); k++) temp+=vec[i][k], cnt++;
}
sort(t.begin(), t.end());
for(int i=0; i<t.size()&&cnt<x; i++){
temp+=t[i];
cnt++;
}
return temp;
}
int main(){
scanf("%d%d", &n, &m);
for(int i=0; i<n; i++){
int p;
ll c;
scanf("%d%lld", &p, &c);
vec[p].push_back(c);
}
for(int i=1; i<=m; i++) sort(vec[i].begin(), vec[i].end(), greater<ll>() );
int l=1, r=n;
ll ans=1LL<<60;
while(l<r-1){
int lmid=l+(r-l+1)/3, rmid=r-(r-l+1)/3;
ll temp1=cal(lmid), temp2=cal(rmid);
if(temp1<temp2){
ans=min(ans, temp1);
r=rmid;
}
else{
ans=min(ans, temp2);
l=lmid;
}
}
for(int i=l; i<=r; i++){
ans=min(ans, cal(i));
}
printf("%lld\n", ans);
return 0;
}