You are running for a governor in a small city in Russia. You ran some polls and did some research, and for every person in the city you know whom he will vote for, and how much it will cost to bribe that person to vote for you instead of whomever he wants to vote for right now. You are curious, what is the smallest amount of money you need to spend on bribing to win the elections. To win elections you need to have strictly more votes than any other candidate.
First line contains one integer n n n ( 1 < = n < = 1 0 5 1<=n<=10^{5} 1<=n<=105 ) — number of voters in the city. Each of the next n n n lines describes one voter and contains two integers a i a_{i} ai? and b i b_{i} bi? ( 0 < = a i < = 1 0 5 ; 0 < = b i < = 1 0 4 0<=a_{i}<=10^{5}; 0<=b_{i}<=10^{4} 0<=ai?<=105;0<=bi?<=104 ) — number of the candidate that voter is going to vote for and amount of money you need to pay him to change his mind. You are the candidate 0 0 0 (so if a voter wants to vote for you, a i a_{i} ai? is equal to zero, in which case b i b_{i} bi? will also be equal to zero).
Print one integer — smallest amount of money you need to spend to win the elections.
5
1 2
1 2
1 2
2 1
0 0
3
4
1 2
1 2
2 1
0 0
2
1
100000 0
0
以上来自 C o d e F o r c e s 以上来自CodeForces 以上来自CodeForces
你正在竞选俄罗斯一个小城市的州长。你做了一些民意调查和研究,知道这个城市里的每个人都会把票投给谁,也知道贿赂这个人把票投给你而不是他现在想投给的人需要多少钱。你很好奇,要想赢得选举,你需要花最少的钱来贿选。要在选举中获胜,你需要拥有严格意义上比其他候选人更多的选票。
第一行包含一个整数 n ( 1 ? ≤ ? n ? ≤ ? 1 0 5 ) n(1?\le?n?\le?10^5) n(1?≤?n?≤?105)–城市中的选民人数。接下来的每 n n n 行描述一个选民,并包含两个整数 a i , b i ( 0 ? ≤ ? a i ? ≤ ? 1 0 5 ; 0 ? ≤ ? b i ? ≤ ? 1 0 4 ) a_i,b_i(0?\le?a_i?\le?10^5;0?\le?b_i?\le?10^4) ai?,bi?(0?≤?ai??≤?105;0?≤?bi??≤?104)–选民将要投票给的候选人的编号,以及你需要付给他多少钱才能让他改变主意。你是候选者 0 0 0(因此,如果投票者想投你的票, a i a_i ai? 等于零,那么 b i b_i bi? 也等于零)。
输出一个整数——赢得选举所需花费的最小金额。
翻译: D e e p L + 本人 翻译:DeepL+本人 翻译:DeepL+本人
可以发现买多少票和花费成正比,所以可以二分需要多少张票,然后问题就会转化成已知要多少张票,然后用贪心求花费的最小值。
考虑怎么买票超过自己的对手:假设需要
x
x
x 张票,那么所有票数大于等于
x
x
x 的人的票都得买走,否则他们就会阻止我当州长;其次,我肯定要买相对便宜的,所以要对票价排序;最后,如果我买了这些票数大于等于
x
x
x 的人的票后还不够
x
x
x 张,那我就不得不从剩下的票池里买了,而且也一定会去买便宜的。以上操作用vector
维护即可。
看上去很难,实际一点都不简单。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int Maxn = 100000;
int n;
vector<int> arry[Maxn + 5];
int ans;
//{
inline void Input();
//
inline void Solve();
inline void init();
inline int Binary_search();
inline bool Check(int mid);
inline int Get_Answer(int x);
//
inline void Output();
//}
inline void work() {
Input();
Solve();
Output();
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
work();
return 0;
}
//{
inline void Input() {
cin >> n;
int a_i, b_i;
for (int i = 1; i <= n; i++) {
cin >> a_i >> b_i;
arry[a_i].push_back(b_i);
}
}
//
inline void Solve() {
init();
ans = Binary_search();
}
inline void init() {
for (int i = 1; i <= Maxn; i++) {
sort(arry[i].begin(), arry[i].end());
}
}
inline int Binary_search() {
int l = 1, r = n, mid;
while (l <= r) {
mid = l + r >> 1;
if (Check(mid)) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return Get_Answer(l);
}
inline bool Check(int mid) {
return Get_Answer(mid) < Get_Answer(mid + 1);
}
inline int Get_Answer(int x) {
int tot = 0, len1 = arry[0].size();
vector<int> veco;
for (int i = 1; i <= Maxn; i++) {
int j = 0, len2 = arry[i].size();
while (len2 >= x) {
tot += arry[i][j++];
len2 -= 1, len1 += 1;
}
while (j < arry[i].size()) {
veco.push_back(arry[i][j++]);
}
}
sort(veco.begin(), veco.end());
for (int i = 0; i < veco.size(); i++) {
if (len1 >= x) {
break;
}
tot += veco[i], len1 += 1;
}
return tot;
}
//
inline void Output() {
cout << ans << endl;
}
//}