分糖果
![](https://img2022.cnblogs.com/blog/2735373/202208/2735373-20220810142432145-86881988.png)
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;
}
时光花火,水月星辰