考点
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 50; int n; double ans, lsum, rsum, a[maxn], b[maxn];
bool cmp(double &x, double &y) { return x > y; }
int main() { cin >> n; for (int i = 1; i <= n; ++i) cin >> a[i] >> b[i]; sort(a + 1, a + 1 + n, cmp), sort(b + 1, b + 1 + n, cmp); int l = 1, r = 1; while (l <= n && r <= n) { while (l <= n && lsum <= rsum) { lsum += a[l], ans = max(ans, min(lsum, rsum) - (l + r - 1)), ++l; } while (r <= n && rsum < lsum) { rsum += b[r], ans = max(ans, min(lsum, rsum) - (l - 1 + r)), ++r; } } cout << fixed << setprecision(4) << ans; return 0; }
|
思路
A与B数组各取任意数量元素(代表顺序无关);设A数组取l
个,其和为lsum
;设B数组取r
个,其和为rsum
;
题目要让min(lsum, rsum) - (l + r)
最大。
两数组各自从大到小排序后,可直接套用贪心,因为很显然:
l
和r
都在增加,必须也要让min(lsum, rsum)
尽可能大;
由于是从大到小排序,显然在相同长度的情况下,A或B数组的前缀和是最大的;
所以l
可直接等价为A数组游标,r
可直接等价为B数组游标;
lsum
可直接等价为A数组的前缀和,rsum
可直接等价为B数组的前缀和;
每次只需要判断lsum
和rsum
谁更小,谁的游标就新增一个(因为要让最小值最大,维持平衡)