Educational Codeforces Round 75 (Rated for Div. 2)E2. Voting (Hard Version)

题目链接:https://codeforces.com/contest/1251/problem/E2

 

题目大意:有n个人要投票,每个人有两个属性m和p,表示当有m个人投票时,他就会免费投票,否则就需要花p元让他投票,问最少花多少钱能让n个人都投票

 

题目思路:E题,过的人这么少,代码竟然如此简单并没有算法,让我挺惊讶的,以后还是不能被人数吓到。

这题贪心非常巧妙。如何才能让花的钱最少?那就尽量能使人免费投票就让他免费投票。所以我们通过人数排序,先计算m比较大的,从大到小,每次把他需要的钱推进优先队列,把i从m遍历到0,表示需要i个人投票才能免费投,那么当优先队列里的人数大于n-i时,那么剩下来还没投加上以及花钱买来的人都已经没法让他免费获得了,那就只能花钱买人。买人买之前最便宜的,为什么一定要之前处理的呢?因为假如你用整体的最小值,很有可能不满足题意,因为可能有个最小值需要的人数非常少,那么在你买了一部分人的情况下,他就已经免费归你了,你没法再买他一次,但是如果倒着来的话,算过的家伙都是目前还等着别人帮忙的,一定没法直接就完成任务,所以需要他们出力

 

以下是代码:

#include
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
const int MAXN = 2e5+5;
const int MOD = 1e9+7;

int n,x,y;
vectorv[MAXN];
priority_queueq;
int main(){
    int _;
    cin>>_;
    while(_--){
        while(!q.empty())q.pop();
        cin>>n;
        rep(i,0,n)v[i].clear();
        rep(i,1,n){
            cin>>x>>y;
            v[x].push_back(y);
        }
        ll ans=0;
        per(i,n,0){
            for(auto u:v[i]){
                q.push(-u);
                if(q.size()>n-i){
                    ans+=-q.top();
                    q.pop();
                }
            }
        }
        cout<

 

你可能感兴趣的:(贪心,思维)