这是一道有一点费脑子的简单题
题意
给出两个长度为 n n n的数列 a a a, b b b,求任意交换两个数列中相同位置的数后(至多两次), ∣ S u m a − S u m b ∣ |{Sum_a-Sum_b}| ∣Suma−Sumb∣的最小值
思路
因为这个交换次数很少,只有 2 2 2,以及这个 n n n的值同样很小,只有 2000 2000 2000,所以我们将这个问题拆开来看:
1 。 1^。 1。考虑不交换,直接输入的时候累加一个 s u m a suma suma和 s u m b sumb sumb,然后做一个减法, f a b s fabs fabs一下即可。
2 。 2^。 2。考虑只交换一次的情况,我们直接 n 2 n^2 n2暴力枚举 a i a_i ai, b j b_j bj即可。
3 。 3^。 3。考虑交换两次的情况,我们可以用 n 2 n^2 n2的暴力枚举出来在 a a a数组中任取两位所有的值, b b b数组同理,然后再用一个双指针更新答案即可。
代码
具体实现见代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <vector>
namespace OI
{
#define pk putchar(' ')
#define ph puts("")
#define fi first
#define se second
template<class T>
T Fabs(T x)
{
return x < 0 ? -x : x;
}
template<class T>
void rd(T &x)
{
x = 0;
int f = 1;
char c;
while (!isdigit(c = getchar())) if (c == '-') f = -1;
do
{
x = (x << 3) + (x << 1) + (c ^ 48);
} while (isdigit(c = getchar()));
x *= f;
}
template<class T>
void pt(T x)
{
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
pt(x / 10);
putchar(x % 10 ^ 48);
}
}
using namespace OI;
using namespace std;
typedef long long ll;
const int N = 2005;
int n, m, a[N], b[N], kind;
ll sa, sb;
vector<pair<int, pair<int, int> > > suma, sumb;
pair<int, int> ans[2];
int main()
{
rd(n);
for (int i = 1; i <= n; i++)
rd(a[i]), sa += a[i];
rd(m);
for (int i = 1; i <= m; i++)
rd(b[i]), sb += b[i];
for (int i = 1; i < n; i++)
for (int j = i + 1; j <= n; j++)
suma.push_back({a[i] + a[j], {i, j}});
for (int i = 1; i < m; i++)
for (int j = i + 1; j <= m; j++)
sumb.push_back({b[i] + b[j], {i, j}});
sort(suma.begin(), suma.end());
sort(sumb.begin(), sumb.end());
ll minx = Fabs(sa - sb);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
ll tmp = Fabs(sa - sb + 2ll * b[j] - 2ll * a[i]);
if (tmp < minx)
{
minx = tmp;
kind = 1;
ans[0] = {i, j};
}
}
for (int i = 0, j = 0; i < (int)suma.size() && j < (int)sumb.size();)
{
ll tmp = (sa - sb + 2ll * sumb[j].fi - 2ll * suma[i].fi);
if (Fabs(tmp) < minx)
{
minx = Fabs(tmp);
kind = 2;
ans[0] = {suma[i].se.fi, sumb[j].se.fi};
ans[1] = {suma[i].se.se, sumb[j].se.se};
}
if (tmp > 0)
i++;
else
j++;
}
pt(minx), ph, pt(kind), ph;
for (int i = 0; i < kind; i++)
pt(ans[i].fi), pk, pt(ans[i].se), ph;
return 0;
}