Official

E - 座席と弁当の確認 / Checking Seats and Lunches Editorial by MMNMM Editorial for printing


\(f _ i\coloneqq{}\)バス \(i\) で全員に弁当を配ることができるなら \(0\) 、できないなら \(1\) とした列 \(f=(f _ 1,f _ 2,\ldots,f _ N)\) を考えます。

休憩プラン \(i\ (1\le i\le M)\) が配布可能であることは、次の条件と同値です。

  • \(f _ {L _ i}+f _ {L _ {i+1}}+\cdots+f _ {R _ i}=0\)

これは、\(f\) の累積和を求めておくことで、ひとつの計画あたり定数時間で判定することができます。

よって、全体で \(O(N+M)\) 時間でこの問題を解くことができます。

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

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

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

    vector<int> S(N), P(N);
    for (int& s : S) {
        cin >> s;
    }
    for (int& p : P) {
        cin >> p;
    }

    vector<int> f(N);
    for (int i = 0; i < N; ++i) {
        f[i] = S[i] < P[i]; // 配ることができないなら 1
    }
    // 累積和を求める
    for (int i = 1; i < N; ++i) {
        f[i] += f[i - 1];
    }
    f.emplace(f.begin()); // 先頭に 0 を入れておく

    for (int i = 0; i < M; ++i) {
        int L, R;
        cin >> L >> R;
        --L;
        cout << (f[R] == f[L] ? "Yes" : "No") << endl; // 区間内の f がすべて 0 なら Yes
    }

    return 0;
}
N, M = map(int, input().split())

S = list(map(int, input().split()))
P = list(map(int, input().split()))
f = [1 if s < p else 0 for s, p in zip(S, P)] # 配ることができないなら 1

# 累積和を求める
for i in range(1, N):
    f[i] += f[i - 1]
f = [0] + f # 先頭に 0 を入れておく

for i in range(M):
    L, R = map(int, input().split())
    L -= 1
    print('Yes' if f[R] == f[L] else 'No') # 区間内の f がすべて 0 なら Yes

posted:
last update: