牛客OJ tokitsukaze and Soldier (优先队列)

题目链接:
我是一个贼帅的传送门儿

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

题解:

需要用到 优先队列 !!!∑(゚Д゚ノ)ノ
首先介绍一下 什么是优先队列( ̄︶ ̄)↗

所谓优先队列,就是队列中的元素都是按照一定规则排序好的 队列。

然后介绍一下 基本使用方法(队列元素为结构体) d(´ω`*)

#include<queue>//头文件还是这个( • ̀ω•́ )✧

//定义优先队列
priority_queue<结构体名> 队列名;//单词有点长,别拼错啦(ノ゚▽゚)ノ
//如:
struct node
{
	int x,y;
	bool operator < (const node &a) const
	{//必须要重载这个小于!!!
		return x<a.x;
	}
}

//优先队列的操作:
q.top();//返回队头元素
q.pop();//出队队头元素
q.push();//入队
q.empty();//判断队列是否为空,空则返回真,非空则返回假
q.size();//返回队列中元素的个数

//接下来就可畅快的使用优先队列啦!

接下来举个栗子ヾ(◍°∇°◍)ノ゙

#include<iostream>
#include<queue>
using namespace std;
struct node
{
	int x,y;
	bool operator < (const node &a) const
	{
		return x<a.x;
		//这里默认是降序排序
		//如果想要升序排序,改为return x>a.x;  即可!
	}
};
priority_queue<node> q;
int main()
{
	int n;
	node t;
	cin>>n;//n组数据
	for(int i=0;i<n;i++)
	{
		cin>>t.x>>t.y;
		q.push(t);
	}
	while(!q.empty())
	{
		t=q.top();
		cout<<t.x<<" "<<t.y<<endl;
		q.pop();
	}
	return 0;
}

测试环节 ヽ(゚∀゚)メ(゚∀゚)ノ ヽ(゚∀゚)メ(゚∀゚)ノ ヽ(゚∀゚)メ(゚∀゚)ノ

输入:
3
1 2
100 2
3 5
输出:
100 2
3 5
1 2

正式进入本题的题解:(✪ω✪)
每个士兵的战力值为v,不希望队伍中的长度超过s。
(本题优先队列中是降序排序!有疑问请上翻找到基本用法(✪ω✪))

首先核心肯定是要根据每个士兵s来操作的,因为每个士兵的s可能都不一样,可能一个大一个小,所以我们在输入完毕之后就 先对所有士兵的s进行降序排序

然后我们 从高到低依次将士兵这个结构体添加到优先队列 中,如果一旦队列的长度小于等于当前要入队的士兵的s,我们只需要出队相应数量的元素即可!

同时在每次入队元素的时候,sum加上入队士兵的战力值,出队的时候sum减去出队士兵的战力值,并且每次for循环结束,利用ans=max(ans,sum)来比较一下修改后的sum值和修改前的sum值,哪个大要哪个!

代码:(^_−)☆

#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#define maxn 100055
#define ll long long int
using namespace std;
struct node
{//士兵的结构体
	int v,s;
	bool operator < (const node &a) const
	{//优先队列的重载
		return v>a.v;
	}
};
node p[maxn];
priority_queue<node> q;
bool cmp(node a,node b)
{//排序s的cmp
	return a.s>b.s;
}
int main()
{
	ll n,v,s,ans,sum;
	while(scanf("%lld",&n)!=EOF)
	{
		ans=0;sum=0;
		for(int i=0;i<n;i++)
		{
			scanf("%d%d",&v,&s);
			p[i].v=v;
			p[i].s=s;
		}
		sort(p,p+n,cmp);//首先对s进行排序
		for(int i=0;i<n;i++)
		{
			if(q.size()<p[i].s)
			{//如果队列的长度并未达到当前入队士兵的s
				q.push(p[i]);
				sum+=p[i].v;
			}
			else if(q.size()==p[i].s)
			{//如果队列的长度和当前入队士兵的s相等
			//那么需要队列出队一个士兵,然后让当前士兵入列
				node t=q.top();
				sum-=t.v;
				q.pop();
				q.push(p[i]);
				sum+=p[i].v;
			}
			else if(q.size()>p[i].s)
			{//如果队列的长度大于当前入队士兵的s
			//则需要一直出队,直到队列元素为s-1个
				while(q.size()>=p[i].s)
				{
					node t=q.top();
					sum-=t.v;
					q.pop();
				}
				q.push(p[i]);
				sum+=p[i].v;
			}
			ans=max(ans,sum);
		}
		printf("%lld\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值