分糖果

n=2时的证明?好像也不算证明,只能说是枚举,枚举一下就知道了:

如果(a, b)在(c, d)之前,前两个人的结果分别是a+b和max(a+b+d,a+c+d),如果(c, d)在(a, b)之前,前两个人的结果分别是c+d和max(c+d+b,c+a+b),把相同的部分消掉,可以发现在a+b+d和在a+c+d中选哪个取决于b和c的大小,在c+d+b和c+a+b中选哪个取决于a和d的大小,分别设出这两对大小关系,就能从两种情况里确定出两个值,这两个值相互比较时再采用消去相等的数的方法,发现每次选到的最优解都满足题解上的式子。

 

点击查看代码
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 5e4 + 2;
const int mod = 1e9 + 7;
const ll INF = 1e18;

int T, n;
ll ans, sum[maxn];

inline ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct node 
{
    int a, b;
    bool operator < (const node &T) const 
    {
        return min(a, T.b) < min(T.a, b);
    }
}p[maxn];

int main()
{
    T = read(); 
    while(T--)
    {
        n = read(); ans = 0;
        for(int i=1; i<=n; i++)
        {
            p[i].a = read(); p[i].b = read();
        }
        sort(p+1, p+1+n);
        for(int i=1; i<=n; i++)
        {
            sum[i] = sum[i-1] + p[i].a;
            ans = max(ans, sum[i-1]+p[i].a) + p[i].b;
        }
        printf("%lld\n", ans);
    }

    return 0;
}
posted @ 2022-08-10 14:36  Catherine_leah  阅读(21)  评论(0编辑  收藏  举报
/* */