(这题好像并不需要优先队列

题意描述
图片说明

看题解的时候看歪了
写成了从小到大枚举,好像发现不需要优先队列只需要排个序就可以了

题解:
枚举士兵限制为1-n的时候的最大值
可以想象的是士兵限制为k时,最大值是所有s大于等于k的前k(或只有不超过k个士兵满足)大的士兵的v之和
暴力做的时间是不可取的
那么可以先将士兵按v从大到小排序
枚举k时,选择最大的并且s大于等于k的前k个v之和,每次暴力不可取。
那么考虑k与k-1的关系(类似dp

图片说明
summ[k-1]指的是在dp[k-1]中s等于k-1的所有士兵之和
newsum[k]指的是在从k-1枚举的前k-1个最大值的末尾开始选择的新的前k大
(不会用LaTeX只能用解释了orz)
感觉越写越乱了,看代码!

代码:

/*
link: https://ac.nowcoder.com/acm/problem/50439
tags: greedy
*/
#include<bits/stdc++.h>
#define to_l(a) ((a)<<1)
#define to_r(a) ((a)<<1|1)
#define lowbit(a) ((a)&(-a))
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
const int int_inf=0x3f3f3f3f;
const ll ll_inf=0x3f3f3f3f3f3f3f3f;
const int max_n=1e5+5;
struct node{
    int v,s;
};
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int i,j;
    int n;
    cin>>n;
    vector<node> a(n);
    vector<ll> summ(n+1); 
    vector<int> cnt(n+1);
    for(i=0;i<n;i++){
        cin>>a[i].v>>a[i].s;
    }
    int size=0;
    ll sum=0,ans=-1;//sum就是每一轮的dp值
    sort(a.begin(),a.end(),[](const node a,const node b) -> bool {
        return a.v>b.v;
    });
    for(j=0,i=1;i<=n;i++){
        sum-=summ[i-1];
        size-=cnt[i-1];
        while(j<n){
            if(a[j].s>=i){
                summ[a[j].s]+=a[j].v;
                size++;
                cnt[a[j].s]++;
                sum+=a[j].v;
            }
            j++;
            if(size==i) break;
        }
        ans=max(ans,sum);
    }
    cout<<ans<<endl;
    return 0;
}