CF620D Professor GukiZ and Two Arrays Solution

这是一道有一点费脑子的简单题

题目链接(洛谷)
CodeForces

题意

给出两个长度为 n n 的数列 a a , b b ,求任意交换两个数列中相同位置的数后(至多两次), S u m a S u m b |{Sum_a-Sum_b}| 的最小值

思路

因为这个交换次数很少,只有 2 2 ,以及这个 n n 的值同样很小,只有 2000 2000 ,所以我们将这个问题拆开来看:

1 1^。 考虑不交换,直接输入的时候累加一个 s u m a suma s u m b sumb ,然后做一个减法, f a b s fabs 一下即可。

2 2^。 考虑只交换一次的情况,我们直接 n 2 n^2 暴力枚举 a i a_i b j b_j 即可。

3 3^。 考虑交换两次的情况,我们可以用 n 2 n^2 的暴力枚举出来在 a a 数组中任取两位所有的值, 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;
}

谢谢

猜你喜欢

转载自blog.csdn.net/qq_43537070/article/details/107590705