1021上午考试T2

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;
}
posted @ 2020-10-22 06:26  C锥  阅读(108)  评论(1编辑  收藏  举报