1021上午考试T2
题目大意:
N个庄家。你可以到庄家那边下注,每次可以猜大猜小,猜一次一元钱。每一次开彩前,你都可以到任意个庄家那里下赌注。如果开彩结果是大,你就可以得到你之前猜大的庄家相应的ai元钱。如果开彩结果是小,你就可以得到你之前猜小的庄家相应的bi元钱。你可以在同一个庄家那里既猜大又猜小(这样是两块钱),也可以什么都不猜(这样不用钱)。但是阴险狡诈的庄家会根据你下注的信息控制开彩的结果,让你赢的钱数尽量少。问怎么样下注,才能赢走最多的钱。输出一个四位小数。
对于100%的数据,1≤n≤100000。
双指针。
一开始看到这题的时候想复杂了,没写出来。听了机房dalao讲解还是很简单的。
我们假设开彩结果是大,那么会赢\(suma\)元,小会赢\(sumb\)元,那么最后多的钱就是\(min(suma, sumb) - x - y\),\(x, y\)代表买大,小买了几张。
然后我们将所有的从大到小排序,然后强制让\(suma\)或\(sumb\)为较小值,然后双指针搞一下就好了。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n;
double ans, a[N], b[N];
int cmp(double a, double b) { return a > b; }
int main() {
cin >> n;
for(int i = 1;i <= n; i++) scanf("%lf %lf", &a[i], &b[i]);
sort(a + 1, a + n + 1, cmp); sort(b + 1, b + n + 1, cmp);
double suma = 0, sumb = 0; int x = 1;
for(int i = 1;i <= n; i++) {
suma += a[i];
while(sumb + b[x] <= suma) {
sumb += b[x];
ans = max(ans, sumb - (i + x));
x ++;
}
if(x > n) break;
ans = max(ans, sumb - (i + x));
}
suma = 0, sumb = 0, x = 1;
for(int i = 1;i <= n; i++) {
sumb += b[i];
while(suma + a[x] <= sumb) {
suma += a[x];
ans = max(ans, suma - (i + x));
x ++;
}
if(x > n) break;
ans = max(ans, suma - (i + x));
}
printf("%.4lf", ans);
return 0;
}