题解 | #tokitsukaze and Soldier#
tokitsukaze and Soldier
https://ac.nowcoder.com/acm/problem/50439
题意:
在每个士兵都有一个对团队人数的限制下,选出战斗力最高的一个团队
思路:
根据每个士兵对团队人数限制的大小,从人数多的到少的,枚举一下对每个人的判断,看一下这个人要不要进来,进来后要不要把一些人删掉。如果人数超了,肯定是要把队里战力最小的拿出去,就可以用一个小根堆来维护。这样维护只要每次删除一些人,或者不加一些人进来,删除一些人肯定是比增加一些人方便的,并且一个团队的大小是由最小的团队人数决定的,这样就相当于把所有的团队组成形式列举出来,选出当前团队人数的战力最大值。
代码:
#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
#define PII pair<int,int>
#define ll long long
#define x first
#define y second
priority_queue<int,vector<int>,greater<int>> q;
const int N=100100;
PII t[N];
bool cmp(PII a,PII b)
{
return a.y>b.y;
return a.x>b.x;
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
t[i]={a,b};
}
sort(t+1,t+n+1,cmp);
ll ans=0,num=0;//num是每个时刻的情况
for(int i=1;i<=n;i++)
{
q.push(t[i].x);//不管这个士兵的战力,先放进来,让优先队列来排序,如果人数超了,把堆顶元素弹出,也就是把最小的元素丢掉,直到符合此时的人数限制
num+=t[i].x;
while(q.size()>t[i].y)
{
num-=q.top();
q.pop();
}
ans=max(ans,num);//每次更新答案
}
printf("%lld\n",ans);
return 0;
}