題意
給你n個人,你需要讓這n個人全部給你投票。讓第i個人給你投票的方法有兩種:給他pi塊錢收買他,或者當前已經有mi個人爲你投票,他就會爲你免費投票。問最少花費多少錢
思路
首先不難發現,這道題可以貪心,在m相等的人裏優先給花費少的人錢。又因爲,如果我們讓某個m=i的人可以免費爲我們投票,則m<=i的其他人,都可以免費給我們投票。所以我們可以從大到小枚舉m,設爲M,更新ans,使得mi=M時,ans爲m>=M的人都已經爲我們投票時的最小花費。所以問題就轉換爲了如何更新ans。
注意我們這個枚舉有一個前提,就是對於每一個M取值,我們都假設了對於m<M的人,我們都已經獲得了他的選票,只不過這個ans的值沒有更新。所以對於每一個M的取值,我們設m=M的人數爲x,m>M中,我們打算白嫖的人的人數爲y,那麼根據假設,我們現在已經獲得了n-y個人的選票。那麼這x個人中,我們最多也可以白嫖n-y-M個人,那麼x中剩下的人,我們就需要去買。用優先隊列記錄一下,把p最小的那些人買了,ans就更新完成了。
代碼
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define rush() int TT;scanf("%d",&TT);for(int TTT=1;TTT<=TT;TTT++)
const int maxn = 2e5+5;
vector<int> v[maxn];
int main() {
rush() {
int n,m,p;
cin>>n;
for(int i=0; i<=n; i++)
v[i].clear();
for(int i=0; i<n; i++) {
cin>>m>>p;
v[m].push_back(p);
}
priority_queue<int, vector<int>, greater<int>> q;
ll ans = 0;
for(int i=n-1; i>=1; i--) {
for(int j=0; j<v[i].size(); j++)
q.push(v[i][j]);
while(q.size()>n-i) {
ans+=q.top();
q.pop();
}
}
cout<<ans<<endl;
}
return 0;
}