Official

F - Move It Editorial by MtSaka


すべての箱に荷物が \(1\) 個ずつある状態にするには、少なくとも \(2\) 個以上荷物があるすべての箱について、箱に荷物を \(1\) 個だけ残してそれ以外の荷物を移動させる必要があります。

\(2\) 個以上の荷物がある箱 \(i\) に入っている \(k(2\leq k)\) 個の荷物の重さを \(w_1,\ldots,w_{k}\) とすると、移動させる必要のある荷物の重さの最小値は、\(\sum_{i=1}^{k}w_i - max(w)\) です。 つまり、すべての箱に荷物が \(1\) 個ずつある状態にするには \(2\) 個以上の荷物がある箱について、この値の総和がかかるコストとしてありえる最小値となります。

また、この最小値を達成することができます。荷物も箱も互いに \(N\) 個ずつあるため、移動させる必要がある荷物の個数は何も入っていない箱の個数と一致します。そのため、移動させる荷物を任意の何も入っていない箱に入れることですべての箱に荷物が \(1\) つずつ入っている状態にすることができます。

実際に実装する際には、各箱に入っている荷物の重さの最大値を管理し、それらの総和をを \(N\) 個の荷物の重さの総和から引くことで答えを求めることができます。

実装例(C++):

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n), w(n);
    vector<int> max_weight(n);
    for (int i = 0; i < n; ++i)
        cin >> a[i];
    for (int i = 0; i < n; ++i)
        cin >> w[i];

    for (int i = 0; i < n; ++i){
        a[i]--;
        max_weight[a[i]]=max(max_weight[a[i]],w[i]);
    }

    const int sum_w=accumulate(w.begin(),w.end(),0);
    const int sum_max=accumulate(max_weight.begin(),max_weight.end(),0);
    cout << sum_w-sum_max << endl;
}

posted:
last update: