[贪心算法] NC50439 优先队列+贪心

题面

link

  在一个游戏中,需要在n个士兵中选出一些士兵组成一个团,第i个士兵的战力为v[i],团的战力是团内所有士兵的战力之和。但是这些士兵有特殊的要求:如果选了第i个士兵,这个士兵希望团的人数不超过s[i]。(如果不选第i个士兵,就没有这个限制。) 问团的战力最大为多少。

  数据范围: n ( 1 ≤ n ≤ 1 0 5 , 1 ≤ v ≤ 1 0 9 , 1 ≤ s ≤ n ) n(1≤n≤10^5, 1≤v≤10^9,1≤s≤n) n(1n1051v109,1sn)

  

分析

  若是某个方案选取的其中一个士兵,其限制为 s i s_i si, 那么能达成的最佳方案就是在所有 s 值大于等于 s i s_i si的士兵中再挑选 s i − 1 s_i - 1 si1个士兵。
  可以将士兵按照s值从大到小排序,依次将士兵插入优先队列中(小顶堆),若是有限队列的元素个数大于当前士兵的s值,那么就一直将队首元素去掉,这样子的队列维护即是上述最佳方案的实现,记录维护过程中的最大值即为所求。
  

代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;

struct node
{
    int s, v;
    bool operator<(const node& m1)
    {
        return s > m1.s;
    }
}pro[maxn];

priority_queue<int, vector<int>, greater<int> > que;
int n;
ll ans, cur;

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%d %d", &pro[i].v, &pro[i].s);
    sort(pro + 1, pro + 1 + n);

    for(int i = 1; i <= n; i++)
    {
        que.push(pro[i].v);
        cur += pro[i].v;
        while(que.size() > pro[i].s)
        {
            cur -= que.top();
            que.pop();
        }
        ans = max(ans, cur);
    }
    printf("%lld\n", ans);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值