NC50439 tokitsukaze and Soldier(贪心)
题目大意
略
解题思路
使用两个优先队列,第一个优先队列以v为第一优先级,s为第二优先级从大到小排序,第二个优先队列以s为第一优先级,v为第二优先级从小到大排序。对于第一个优先队列堆顶的一对(v,s)来说,如果s我们选出的所有数的数量小,就不需要他了,因为我们以v的大小为第一优先级,加上他最少需要减去一个比他更大的数,然后我们把符合条件的数加入第二个优先队列。
由于可能有前面v比较大的数s比较小,当s最小的数的s已经比当前选出的数小时,需要去掉这个数来给其他的数腾出位置,这就是第二个优先队列的意义。
代码
const int maxn = 1e5+10;
const int maxm = 1e4+10;
struct INFO {
int v, s;
bool operator < (const INFO &a) const {
return v==a.v ? s<a.s:v<a.v;
}
};
struct INFO2 {
int v, s;
bool operator < (const INFO2 &a) const {
return s==a.s ? v>a.v:s>a.s;
}
};
int n;
priority_queue<INFO> pq;
priority_queue<INFO2> pq2;
int main(void) {
cin >> n;
ll sum = 0, ans = 0;
for (int i = 0, a, b; i<n; ++i) {
scanf("%d%d", &a, &b);
pq.push({a, b});
//cout << pq.top().v << endl;
}
while(!pq.empty()) {
int a = pq.top().v, b = pq.top().s; pq.pop();
if (b<=pq2.size()) continue;
pq2.push({a, b});
sum += a;
if (pq2.top().s<pq2.size()) sum -= pq2.top().v, pq2.pop();
ans = max(ans, sum);
}
cout << ans << endl;
return 0;
}