codeforces 1251E1/E2 Voting

Codeforces 1251E1/E2 Voting

题意

给你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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章