Npc50C [贪心]

N p c   50 C Npc\ 50C Npc 50C

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

1 ≤ n ≤ 1 0 5 1≤n≤10^5 1n105
1 ≤ v ≤ 1 0 9 , 1 ≤ s ≤ n 1≤v≤10^9,1≤s≤n 1v109,1sn


正 解 部 分 \color{red}{正解部分}

发现如果按照 v [ i ] v[i] v[i] 从大到小贪心的话, 团的人数限制不好处理, 因为不知道是哪个士兵限制了团的人数大小 .

于是按照 s [ i ] s[i] s[i] 从大到小排序, 从左往右选择士兵, 限制团大小的士兵肯定包括 i i i 和 与 i i i s [ i ] s[i] s[i] 相等的士兵,

i i i 这个士兵的限制下, 要尽量使得战力更大, 即选择最大的, 丢弃最小的,
于是可以使用小根堆维护当前的士兵集合, 若不符合条件, 就不断地往外弹出 v v v 最小的士兵, 直到符合条件, 更新答案 .


实 现 部 分 \color{red}{实现部分}

#include<bits/stdc++.h>
typedef long long ll;
#define reg register

const int maxn = 1e5 + 10;

int N;

ll Ans;
ll cur_sum;

struct Node{ int s, v; } A[maxn];

bool cmp(Node a, Node b){ return a.s > b.s; }

int main(){
        scanf("%d", &N);
        for(reg int i = 1; i <= N; i ++) scanf("%d%d", &A[i].v, &A[i].s);
        std::sort(A+1, A+N+1, cmp);
        std::priority_queue <int, std::vector<int>, std::greater<int> > Q;
        for(reg int i= 1; i <= N; i ++){
                Q.push(A[i].v), cur_sum += A[i].v;
                while((int)Q.size() > A[i].s) cur_sum -= Q.top(), Q.pop();
                Ans = std::max(Ans, cur_sum);
        }
        printf("%lld\n", Ans);
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值