题目链接:Codeforces - Elections
直接去二分1号人物的票数,但是不满足二分性,这是一个凹槽。所以我们三分即可。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3010;
int n,m,cnt[N],res=1e18;
vector<int> v[N],g;
inline int check(int mid){
int need=mid-cnt[1],res=0; g.clear();
for(int i=2;i<=m;i++){
for(int j=0;j<v[i].size();j++) if(v[i].size()-j>=mid){
need--; res+=v[i][j];
}else g.push_back(v[i][j]);
}
sort(g.begin(),g.end());
for(int i=0;i<need;i++) res+=g[i];
return res;
}
signed main(){
cin>>n>>m;
for(int i=1,x,y;i<=n;i++){
cin>>x>>y;
if(x==1||y==0) cnt[1]++;
else v[x].push_back(y),cnt[x]++;
}
for(int i=2;i<=m;i++) sort(v[i].begin(),v[i].end());
int flag=0;
for(int i=2;i<=m;i++) if(cnt[i]>=cnt[1]) flag++;
if(!flag) return puts("0"),0;
int l=cnt[1],r=n;
while(l<=r){
int midl=l+(r-l)/3,fl=check(midl);
int midr=r-(r-l)/3,fr=check(midr);
if(fl<=fr) r=midr-1,res=min(res,fl);
else l=midl+1,res=min(res,fr);
}
cout<<res;
return 0;
}