题意:
有3个集合,每个集合里有若干个数
你可以选2个来自不同集合的数x、y,然后让2个数同时减去x
经过若干次操作后,只剩下1个数
问剩下的这个数最大可以是多少
操作相当于把一个集合里的数变号,然后放到另一个集合中并与集合中的某个数相加
设集合A中有a[1] a[2] a[3],集合B中有b[1] b[2] b[3],集合C中有c[1] c[2] c[3]
假设我们现在把a[1]变号放到B里并和b[1]相加,会变为
a[2] a[3],b[1]-a[1] b[2] b[3],c[1] c[2] c[3]
把b[1]-a[1]变号放到C里并和c[1]相加,会变为
a[2] a[3],b[2] b[3],c[1]-b[1]+a[1] c[2] c[3]
这一步相当于a[1]是被第2次放,它又变回了正号
可以看出,一个数如果被放了奇数次是负号,偶数次是正号
一个数来回放只是符号改变,所以直接让每个数放<=2次即可(即放奇数次直接放去目标位置,放偶数次中间只中转一次)
因为最后要变为1个数,所以必然存在1个数他被放了1次,这个数是负号
我们选这个数为3个集合里最小的数x
除了这个x所在集合,其余2个集合的数都可以在x中转一次,从而最终是正号
对于x所在集合的其他数,要么再在另外2个集合选最小的数作为中转,从而最终为正好;要么和x一样直接去最终位置,最终为负号
所以最终的答案是以下6种中最大的
1、总和-2*集合1的和
2、总和-2*集合2的和
3、总和-2*集合3的和
4、总和-2*(集合1最小数+集合2最小数)
5、总和-2*(集合1最小数+集合3最小数)
6、总和-2*(集合2最小数+集合3最小数)
#include<bits/stdc++.h> using namespace std; #define N 300003 int a[4][N]; int main() { int n[4]; for(int i=1;i<=3;++i) scanf("%d",&n[i]); long long tot[4]={0,0,0,0},mi,ans; for(int i=1;i<=3;++i) { for(int j=1;j<=n[i];++j) { scanf("%d",&a[i][j]); tot[i]+=a[i][j]; } sort(a[i]+1,a[i]+n[i]+1); } mi=a[1][1]+a[2][1]; mi=min(mi,min((long long)a[1][1]+a[3][1],(long long)a[2][1]+a[3][1])); mi=min(min(min(tot[1],tot[2]),tot[3]),mi); ans=tot[1]+tot[2]+tot[3]-mi-mi; printf("%lld",ans); }