本题是一个可后悔的贪心,首先从简单来看,如果单纯根据战力选择可能会因为人数现在而没有达到最优,如果根据人数限制选择,可能会出现极端战力导致错误。
但如果两个条件其中之一我们已知的话求解起来就比较简单了,如果我们已知人数限制,那么只需要在所有人数限制超过这个的人里面选最好的几个就行了。这看起来很像二分答案的思路,
但因为战力总和相对于人数并不单调,无法采用二分的方式。在这里采用从人数大到小枚举的方式,因为人数在从大到小,所以原来人数限制大的哪些士兵是不需要退出的,因为他们本来人数限制就可以容忍。但因为会有新的士兵进来,所以可能会将战力底的老士兵给挤掉,所以在这里建立一个小根堆来维护最小的战力。然后每一个人数下都有一个最优的战力,取最大值即可。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 1e5+10;
struct Node {
int v;//战力
int s;//人数
} node[maxn];
priority_queue<int, vector<int>, greater<int> > pq;
bool comp(Node n1, Node n2) {
return n1.s>n2.s;
}
int main() {
int n;
cin>>n;
for (int i=0;i<n;i++) {
cin>>node[i].v;
cin>>node[i].s;
}
sort(node, node+n, comp);
ll ans = 0, Ans;
for (int i=0;i<n;i++) {
int xz = node[i].s;
if ((pq.size()+1)<=xz) {
pq.push(node[i].v);
ans+=node[i].v;
} else if ((pq.size()+1)>xz) {
if (pq.top()<node[i].v) {
ans-=pq.top();
pq.pop();
pq.push(node[i].v);
ans+=node[i].v;
}
}
while (pq.size()>xz) {
ans -= pq.top();
pq.pop();
}
Ans = max(ans, Ans);
}
cout<<Ans;
return 0;
}

京公网安备 11010502036488号