比赛-ZR DAY4 (07 Aug, 2018)
A. 世界杯
假设法国队的赔率是 \(x\) ,则第 \(i\) 个人下注法国队的充要条件是
\[(x-1)\cdot a_{i}\cdot p_{i}-a_{i}\cdot (1-p_i)\geq 0
\]
化简一下就是
\[x\geq\frac{1}{p_i}
\]
类似的可以得出下注克罗地亚队的充要条件(假设赔率是 \(y\) )
\[y\geq \frac{1}{1-p_i}
\]
把 \(p_i\) 从大到小排序,显然下注法国队的是前缀 \([1, l]\) ,下注克罗地亚队的是一个后缀 \([r, n]\) 。彩票公司的利益是
\[\sum a[1...l]+\sum a[r...n]-max\left(\sum a[1...l]\cdot x, \sum a[r...n]\cdot y\right)
\]
然后可以贪个心,当 \(max\) 内取前一项时考虑把 \(r\) 减去 \(1\) ,取后一项时考虑把 \(l\) 加上 \(1\) 。这样很可能不会改变 \(max\) 的取值,而使前面的式子的取值变大,它就很好。就是这样。
#include <cstdio>
#include <algorithm>
using namespace std;
const int _N = 1020000;
struct data {
double a, p;
bool operator < (const data &tmp) const
{
return p > tmp.p;
}
} A[_N];
int main()
{
// freopen("ex_a2.in", "r", stdin);
int N;
double ans = 0;
scanf("%d", &N);
for (int i = 1; i <= N; ++i) scanf("%lf%lf", &A[i].a, &A[i].p);
sort(A+1, A+1+N);
int l = 1, r = N;
double suml = A[1].a, sumr = A[N].a;
while (l <= N && r >= 1) {
double x = 1/A[l].p, y = 1/(1-A[r].p);
ans = max(ans, suml+sumr-max(suml*x, sumr*y));
if (suml*x > sumr*y) sumr += A[--r].a;
else suml += A[++l].a;
}
printf("%.6lf\n", ans);
return 0;
}
B. 数组
C. 淘汰赛