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;
}
posted @ 2020-10-04 09:37  shuitiangong  阅读(132)  评论(0编辑  收藏  举报