题目链接:https://ac.nowcoder.com/acm/contest/1080/C
题目大意:给出n个士兵,每个士兵有v,s两个属性,分别指个人战斗力和组团限制人数(该士兵所在兵团最大人数值),问如何选择士兵,使得战斗力总和最大?
题目解答:可以给士兵按照s从大到小排序,用一个小根堆来贪心维护战斗力总和,通过遍历士兵,不断地调整小根堆(优先队列)。(大局上是枚举不同的s,确保从大到小尝试,队列里始终保持最优解,因为我们会动态地把队列里不满足s限制且战斗力最小的弹出)
代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=1e5+5;
int v[maxn],s[maxn];
int n;
struct node
{
int v,s;
}bt[maxn];
bool cmp(node a,node b)
{
if(a.s!=b.s)
return a.s>b.s;
else
return a.v>b.v;
}
int main()
{
//ios::sync_with_stdio(false);
cin>>n;
for(int i=0;i<n;i++)
{
int v,s;
cin>>v>>s;
bt[i].v=v;
bt[i].s=s;
}
sort(bt,bt+n,cmp);
priority_queue<int,vector<int>,greater<int> >q;
LL sum=0;
LL ans=0;
for(int i=0;i<n;i++)
{
sum+=bt[i].v;
q.push(bt[i].v);
while(q.size()>bt[i].s)
{
sum-=q.top();
q.pop();
}
ans=max(ans,sum);
}
cout << ans << endl;
return 0;
}