题目链接:
我是一个贼帅的传送门儿
题目大意:
在一个游戏中,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;
}