牛客练习赛50 C.tokitsukaze and Soldier (优先队列+贪心)

C.tokitsukaze and Soldier

链接:https://ac.nowcoder.com/acm/contest/1080/C

来源:牛客网

题目描述

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

输入描述:

第一行包含一个正整数n(1≤n≤10^5)。
接下来n行,每行包括2个正整数v,s(1≤v≤10^9,1≤s≤n)。

输出描述:

输出一个正整数,表示团的最大战力。

分析:

按s从大到小排序,
优先队列(小根堆)存已经选择的士兵的战力v
从大到小选择s,
已经选择的士兵人数一定小于当前选择的s
如果选择当前士兵后超过了人数限制,就让v最小的士兵出队知道满足人数限制

对每次的结果取max就是答案

code:

#include
#include
#include
#include
#include
#include
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=1e5+5;
struct Node{
    int v,s;//v是战力,s是人数限制
}a[maxm];
bool cmp(Node a,Node b){
    return a.s>b.s;
}
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i].v>>a[i].s;
    }
    sort(a+1,a+1+n,cmp);
    ll ans=0;//最大战力
    ll now=0;//当前战力
    int num=0;//当前人数
    int limit=inf;//最大人数
    priority_queue<ll,vector<ll>,greater<ll>>q;
    for(int i=1;i<=n;i++){
        limit=min(limit,a[i].s);
        q.push(a[i].v);
        num++;
        now+=a[i].v;
        while(num>limit){
            ll x=q.top();
            q.pop();
            now-=x;
            num--;
        }
        ans=max(ans,now);
    }
    cout<<ans<<endl;
    return 0;
}

你可能感兴趣的:(优先队列)