ACM模版

描述

题解

贪心问题,不过贪心思路不是特别明了……

首先我们将两个序列都进行排序,然后分别考虑往 a 序列还是 b 序列凑(复制),当然,复制的时候并不是说将某一个序列里的所有元素都复制到另一个序列的所有块儿,而是将某一个序列的所有元素都复制到另一个序列的部分块儿,而后者序列的其他块儿也要复制过来,所以呢,我们需要判断怎么贪心选取块儿比较划算,这个部分看代码就能懂,说起来都是麻烦一些,就是从小到大枚举,当某一个块儿的信息数大于另一个块儿的总信息数就说明大于等于这个块儿的都要选取,而如果所有块儿都没有另一个总信息量大时,我们还需要特别考虑一下只取最大的情况。

听起来可能有些迷糊,但是看一下代码就清晰多了,所以不再多说了~~~

代码

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;

const int MAXN = 1e5 + 10;
const ll INF = 0x3f3f3f3f3f3f3f3f;

int n, m;
ll a[MAXN], b[MAXN];

template <class T>
inline void scan_d(T &ret)
{
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9')
    {
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}

int main()
{
    scan_d(m), scan_d(n);

    ll sum_a = 0, sum_b = 0;
    for (int i = 0; i < m; i++)
    {
        scan_d(a[i]);
        sum_a += a[i];
    }
    for (int i = 0; i < n; i++)
    {
        scan_d(b[i]);
        sum_b += b[i];
    }
    sort(a, a + m);
    sort(b, b + n);

    ll ans = INF;
    ll sum = 0;
    for (ll i = 0; i < m - 1; i++)
    {
        if (sum_b <= a[i])
        {
            sum += (m - i) * sum_b;
            ans = min(ans, sum);
            break;
        }
        sum += a[i];
    }
    ans = min(ans, sum + sum_b);

    sum = 0;
    for (ll i = 0; i < n - 1; i++)
    {
        if (sum_a <= b[i])
        {
            sum += (n - i) * sum_a;
            ans = min(ans, sum);
        }
        sum += b[i];
    }
    ans = min(ans, sum + sum_a);

    printf("%lld\n", ans);

    return 0;  
}