牛客练习赛50 C. tokitsukaze and Soldier (贪心、队列维护)

题目链接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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值