Official

A - 温度管理と収穫判定 / Water Management and Harvest Value Aggregation Editorial by MMNMM


初心者の方へ

それぞれの区画の収穫価値、現在の水分量、閉鎖されているかを並べた配列を使い、操作 1, 3 を for 文などを使って処理することで、それぞれのクエリは \(O(N)\) 時間で処理することができます。

全体で \(O(QN)\) 時間で解くことができ、この問題の制約のもとで十分高速です。

実装例は以下のようになります。

閉鎖する区画に十分巨大な水分量を与えることで、閉鎖されているかの配列を個別に作成しなくてもよくなります。 この読み替えによって変数が減り条件式もシンプルになりますが、水分量の配列が指すものが複雑になります。 このような変形は、それぞれの変数が指しているものについて混乱しないところを見極めて行うのがよいでしょう。

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int N, Q;
    cin >> N >> Q;

    vector<int> S(N), C(N);
    // 閉鎖されているなら true
    vector<bool> closed(N, false);

    for (int& s : S) {
        cin >> s;
    }
    for (int& c : C) {
        cin >> c;
    }

    for (int q = 0; q < Q; ++q) {
        int t;
        cin >> t;
        if (t == 1) {
            int l, r, v;
            cin >> l >> r >> v;
            --l; // l, r を 0-indexed 右半開区間にする
            for (int i = l; i < r; ++i) {
                C[i] += v; // 水分量を更新
            }
        } else if (t == 2) {
            int x;
            cin >> x;
            --x; // 0-indexed にする
            closed[x] = true; // 閉鎖
        } else {
            int l, r;
            cin >> l >> r;
            --l; // l,r を 0-indexed 右半開区間にする
            long ans = 0;
            for (int i = l; i < r; ++i) {
                if (!closed[i] && C[i] <= 0) { // 閉鎖されていなくて水分量が 0 以下なら
                    ans += S[i]; // 収穫価値を足す
                }
            }
            cout << ans << endl;
        }
    }
    return 0;
}
N, Q = map(int, input().split())

S = list(map(int, input().split()))
C = list(map(int, input().split()))
closed = [False for _ in range(N)]

for i in range(Q):
    t, *q = map(int, input().split())
    if t == 1:
        l, r, v = q
        l -= 1 # l, r を 0-indexed 右半開区間にする
        for i in range(l, r):
            C[i] += v # 水分量を更新
    elif t == 2:
        x, = q
        x -= 1 # 0-indexed にする
        closed[x] = True # 閉鎖
    else:
        l, r = q
        --l # l, r を 0-indexed 右半開区間にする
        print(sum(S[i] for i in range(l, r) if not closed[i] and C[i] <= 0)) # 閉鎖されていなくて水分量が 0 以下の区画の収穫価値の合計

posted:
last update: