0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C++】ABC396 C.Buy Balls 解説

Last updated at Posted at 2025-03-21

はじめに

こんにちは!競技プログラミングをやっている学生のmikan0131です!
今回は久しぶりにAtCoderの解説をしていこうと思います!

問題文

要するに、一番価値が高くなるように黒・白のボールを選べ、でも黒の数$\ge$白の数だよってことみたいです。
それでは、解いていきましょう。

解説

とりあえず、必要な値を入力しましょう。

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

int N, M;
int B[200009], W[200009];

int main() {
    cin >> N >> M;
    for (int i = 1; i <= N; i++) cin >> B[i];
    for (int j = 1; j <= M; j++) cin >> W[i];
    return 0;
}

ひとまず、ここまでで入力は終了です。
では、ここからどうしましょうか?

まず、当たり前の話ですが、価値の値が負のボールを選ぶと、価値の総和は下がりますし、正のボールを選ぶと、価値の総和は上がります。なので、できれば価値の値が正のボールを全部選びたい!
しかし、ここで問題になるのは、問題の条件である「(黒のボールの個数)$\ge$(白のボールの個数)」というところです。
もし、正の価値のボールをすべて選んでも、その時に選んだ黒のボールの数が白のボールの数より多かったら条件は成り立たなくなってしまいます。
それなら、どうすればいいのでしょうか?さすがに全部試すのも間に合わないし…
そこで、思いついたのが黒、白どちらのボールの価値もソートしてから、二つ同時に大きい順から試すという方法です。
どういうことかというと、配列$B$・$W$をソートかつリバースし、大きい順に並べます。
そして、大きいほうから順に黒と白の価値を同時にみていって、下の図のような条件で価値を決める方法です。
どちらも正の価値の時は当然それらのボールの価値の和答えにを足す。
黒が負の価値の時は、白の正の価値を足すために黒のボールも追いつく必要がありますが、それで価値がマイナスになると本末転倒なので、黒と白の価値の和が正の時だけ答えに足す。
白が負の価値の時は、黒だけ足せば問題ないので、黒の価値を足す。
さらに、どちらも負の時は当然どちらも足さない。
スクリーンショット 2025-03-21 203105.png
このようにしてみていけば、$O(N)$で答えを求めることができます。

解答

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;//値がint型におさまらない(おさまるわけない)ので、long long型にする

ll N, M;
ll B[200009], W[200009];

int main() {
    //入力
    cin >> N >> M;
    for (ll i = 1; i <= N; i++) cin >> B[i];
    for (ll i = 1; i <= M; i++) cin >> W[i];
    //B, Wをソート
    sort(B + 1, B + N + 1);
    sort(W + 1, W + M + 1);
    reverse(B + 1, B + N + 1);
    reverse(W + 1, W + M + 1);
    ll ans = 0;
    //解説のように条件分岐をしながら見ていく(途中breakがあるのは余計な計算を省くためで、正直なくてもいい)
    for (ll i = 1; i <= N; i++) {
        if (B[i] >= 0 && W[i] >= 0) {
            ans += B[i] + W[i];
        }
        else if (B[i] >= 0 && W[i] < 0) {
            ans += B[i];
        }
        else if (B[i] < 0 && W[i] >= 0) {
            if (B[i] + W[i] >= 0) {
                ans += B[i] + W[i];
            }
            else {
                break;
            }
        }
        else {
            break;
        }
    }
    cout << ans << endl;
    return 0;
}

おわりに

読んでくれた方、ありがとうございました!
解説、わかりにくかったらごめんなさい
この解説で分かってくれた人はこの解説をupsolvingに役立ててくれたらうれしいです!
ありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?