【CF1467C】Three Bags 题解

https://codeforces.com/contest/1467/problem/C

题意

有三个袋子,里面分别装有 n 1 , n 2 , n 3 n_1,n_2,n_3 n1,n2,n3 个数字。可以对这些数字进行如下操作:从任意两个袋子里各选一个数字,分别为 a , b a,b a,b,将 a a a 改为 a − b a-b ab,将 b b b 删去。
在若干次操作后,只剩一个数字,求这个数的最大值

分析

假设三个袋子分别为 A , B , C A,B,C A,B,C 。题目给出的操作可以看作是将 b b b − 1 -1 1 后,移到装有 a a a 的袋子里。我们的目标就是把所有数移到同一个袋子里。假设要把所有数都移到 A A A 中,那么

考虑移动一个数

例如,将 x x x B B B 移到 A A A,有两种方法

  1. 直接把 x x x 移到 A A A x x x 变成 − x -x x
  2. x x x 先移到 C C C 中,变为 − x -x x;再从 C C C 移到 A A A 中,变回 x x x

按照题目给出的操作,移动时还需在要移入的袋子里找另一个数,仍以将 x x x B B B 移到 A A A 为例,前文给出的两种方法需要改成

  1. 直接把 x x x 移到 A A A:在 A A A 中找一个数 y y y 变成 y − x y-x yx B B B 里的 x x x 删去
  2. x x x 先移到 C C C 中,再从 C C C 移到 A A A:在 C C C 中找一个数 y y y 变成 y − x y-x yx B B B 中的 x x x 删去;在 A A A 中找一个数 z z z 变成 z + x − y z+x-y z+xy z − ( y − x ) z-(y-x) z(yx)), C C C 中的 y − x y-x yx 删去

不难发现,使用第二种方法,可以看作将 x x x 直接移入 A A A,但是 y y y 会被减去。

移动所有数

用上述方法,要将所有数依次移入 A A A 中,需要在 B B B 和/或 C C C 中选取一个或一些数用于中转,这些用于中转的数最后被减去,其他数则是直接被 “移入” A A A。可以分以下两种情况讨论

  1. B B B C C C 中分别选取一个/一些数用于中转。由于用于中转的数最后会被减去,因此应该分别选两个袋子里最小的一个。
  2. B B B C C C 中选取一个/一些作为中转。假设选取 B B B 中的数用于中转,则要将 C C C 中的数全部移入 B B B ,再将 B B B 中的数移入 A A A。那么,原来属于 C C C 的数被 “移入” A A A;由于 C C C 中没有用于中转的数,原来属于 B B B 的数全部变负,也就是必须选取整个袋子的所有数。

两种方法最后的答案都是 中转数的和 - 非中转数的和,但中转数的选取不同,答案也不同。分别计算这两种方法得到的答案,取较大的即可。

代码

#include<iostream>
using namespace std;

typedef long long ll;

const int maxn = 3e5 + 5;
ll a[maxn], b[maxn], c[maxn];

int main()
{
	int n1, n2, n3;
	scanf("%d%d%d", &n1, &n2, &n3);
	
	ll sum[3] = {};
	ll ma, mb, mc;
	ma = mb = mc = 1e9;
	for(int i = 0; i < n1; i ++)
	{
		scanf("%d", &a[i]);
		ma = min(ma, a[i]);
		sum[0] += a[i];
	}
	for(int i = 0; i < n2; i ++)
	{
		scanf("%d", &b[i]);
		mb = min(mb, b[i]);
		sum[1] += b[i];
	}
	for(int i = 0; i < n3; i ++)
	{
		scanf("%d", &c[i]);
		mc = min(mc, c[i]);
		sum[2] += c[i];
	}
	
	ll tmp1 = min(ma + mb, min(mb + mc, mc + ma));
	ll tmp2 = min(sum[0], min(sum[1], sum[2]));
	ll ans = sum[0] + sum[1] + sum[2] - 2 * min(tmp1, tmp2);
	printf("%lld\n", ans);
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值