虽然贪心算法是入门算法,也是接触最早的一个算法:是一种在每一步选择中采取当前状态下最优局部决策的算法。但难的贪心算法题目经常会让人无从下手或者朝着看似正确的方法去做。

直接按照人数上限从大到小排序,然后用小根堆存入目前所有选择士兵的战斗力,那么堆顶就是所有士兵中最菜的一个
排完序后,从第个士兵依次遍历到第个士兵,因为我们是按照人数上限从大到小排序,所以决定目前所选士兵总人数的是目前考虑到第个士兵的
那么会发生下面两种情况:
  1. 如果,这表示我们所选择的士兵人还没有等于或者超过第个士兵的人数限制,那么我们可以直接将这个士兵选择进来
  2. 如果,那么我们就需要根据小根堆一直删除知道所选择士兵的数量刚好等于(必须要这么做,也就是说必须要选择第,否则会遗漏情况)
总代码:
#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;


bool cmp(pair<int, int> a, pair<int, int> b){
    return a.second > b.second;
}

signed main(){
    HelloWorld;
    
    int n; cin >> n;
    vector<pair<int, int> > a(n + 1);
    for(int i = 1; i <= n; i ++) cin >> a[i].first >> a[i].second;
    sort(a.begin() + 1, a.begin() + 1 + n, cmp);

    int ans = 0, res = 0;
    priority_queue<int, vector<int>, greater<int> > q;
    for(int i = 1; i <= n; i ++){
        if(q.size() < a[i].second){
            q.push(a[i].first);
            res += a[i].first;
            ans = max(ans, res);
        }
        else{
            while(q.size() >= a[i].second){
                int now = q.top();
                res -= now;
                q.pop();
            }
            res += a[i].first;
            q.push(a[i].first);
            ans = max(ans, res);
        }
    }
    cout << ans << endl;
    return 0;
}