Official

F - Kaiten Sushi Editorial by yuto1115

解説

\(K=\max B_i\) とおきます。

具体的な解法を説明する前に、美味しさ \(1,2,\dots,K\) の寿司が \(1\) つずつ流れてきたときに何が起こるかを考えてみましょう。このとき、\(i=1,2,\dots,N\) の順に以下のことが起こります:

  • 残っている寿司の中に美味しさが \(A_i\) 以上のものがあるならば、それらをすべて人 \(i\) が取って食べる。次の人 \(i+1\) には美味しさ \(1,2,\dots,A_i-1\) の寿司が \(1\) つずつ流れることになる。

美味しさ \(i\) の寿司が流れたきたときにそれを食べる人の番号(誰も食べないならば \(-1\))を \(\text{id}_i\) と定義します。(なお、同じ美味しさの寿司は常に同じ人によって食べられるということを前提の考察としています。) 前段落で述べた内容をふまえると、\(\text{id}_1,\text{id}_2,\dots,\text{id}_K\) を以下のようにして求められることが分かります:

  • 変数 \(r\) を用意し、\(r\leftarrow K\) と初期化する
  • \(i=1,2,\dots,N\) の順に以下を行う:
    • \(A_i \leq r\) ならば、\(j=A_i,A_i+1,\dots,r\) それぞれについて \(\text{id}_j \leftarrow i\) とし、\(r\leftarrow A_i-1\) と更新する
  • \(j=1,2,\dots,r\) それぞれについて \(\text{id}_j \leftarrow -1\) とする

\(\text{id}_1,\text{id}_2,\dots,\text{id}_K\) をすべて求めてしまえば、美味しさ \(B_i\ (1\leq i\leq M)\) の寿司を食べる人の番号は \(\text{id}_{B_i}\) の値を参照するだけで求められます。

よって本問題を \(O(N+M+\max B_i)\) で解くことができました。

実装例 (C++) :

#include <bits/stdc++.h>

using namespace std;

const int K = 200010;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<int> id(K, -1);
    int r = K;
    for (int i = 0; i < n; i++) {
        int a;
        cin >> a;
        while (r > a) {
            --r;
            id[r] = i + 1;
        }
    }
    for (int i = 0; i < m; i++) {
        int b;
        cin >> b;
        cout << id[b] << '\n';
    }
}

posted:
last update: