【每日一题】3-24 tokitsukaze and Soldier

题目链接:

题意:

有 n 个士兵,每个士兵有两个值 v[i], s[i],分别表示第 i 个士兵的战斗力 v[i] 和他的限制人数 s[i]
限制人数的意思是,如果选择这个士兵 k,那么选择的人数不能超过 s[k]
求选择若干个士兵的最大战斗力。

解法:

首先考虑为了使若干个士兵的最大战斗力最大,我们肯定希望人数尽量多,并且他们的战斗力尽量高。
所以我们首先将士兵按照限制人数 s[i] 从大到小排序,为了使人数最多,我们从左往右取士兵,考虑一下边界情况,由于士兵是按照限制人数从大到小排序的,所以可选的人数一定是当前遍历到的士兵的可选人数,然后如果我们接着加入士兵发现超过了可选人数,我们显然希望将战斗力更低的士兵删掉,所以要选择一个数据结构在维护他,我们重新看一下需要,加入一个元素,将战斗力最低的元素拿出来,并删掉,这不就是优先队列嘛,所以在遍历的同时,有优先队列来维护一下选择的士兵就可以了

代码:

#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
#define pi pair<int,int>
using namespace std;
pi a[100005];
auto cmp = [](pi q, pi w) {
    return q.first > w.first;
};
int main()
{
    int n;
    sc("%d", &n);
    for (int i = 0; i < n; i++)
        sc("%d%d", &a[i].first, &a[i].second);
    sort(a, a + n, [](pi q, pi w) {
        return q.second > w.second;
    });
    ll ans = 0, sum = 0;
    int sz = 0;
    priority_queue<pi, vector<pi>, decltype(cmp)>q(cmp);
    for (int i = 0; i < n; i++)
    {
        q.push(pi{ a[i].first,a[i].second });
        sz++;
        sum += a[i].first;
        while (sz > a[i].second)
        {
            sum -= q.top().first;
            q.pop();
            sz--;
        }
        ans = max(ans, sum);
    }
    printf("%lld\n", ans);
}


全部评论

相关推荐

01-24 12:50
门头沟学院 C++
投票
菜狗二号:还有啥想的 指定国有行啊,去了就开始幸福美满的生活了,选华子不是折腾自己么,最终财富积累度是差不多的,但是幸福指数是相差甚远的
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
2024-12-30 18:02
程序员牛肉:1.可以标记一下自己的学校是985,有一些hr可能没想到你这个院校是985的。 2.简历所呈现出来的能力还是有点差的,苍穹外卖+黑马点评。这在java技术域里面也就是刚学三四个月的样子,大厂现在招人少,小厂又更加希望你能直接过来干活。就你简历上呈现出来的能力,确实是有点难找,肉眼可见的不懂技术。 第一个项目中:简单的使用redis也算是亮点嘛?使用jwt,threadlocal也算是亮点?你不就是调了几个包嘛?Nginx作为服务器也能写出来,这不是前端的活嘛? 第二个项目中:分布式锁+mq消息队列+Lua队列。真没啥好问的。属于面试官看一眼就阳痿的简历,没有任何想提问的欲望。 我给你建议是好好的挖一挖这个项目吧,其实苍穹外卖和黑马点评这两个项目很不错了,只不过是太烂大街了导致面试官没啥问的兴趣,所以不太推荐写简历上。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务