NC50439 tokitsukaze and Soldier(貪心)
阿新 • • 發佈:2020-10-04
題目大意
略
解題思路
使用兩個優先佇列,第一個優先佇列以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; }