計算量を抑えて最小値の探索を行うのがコツで,今回の問題ではこの能力が問われました.E問題レベルになると説明がかなり難しく,自分の日本語力が問われているような気がします…
問題
公式の問題はコチラ.
問題文
ここで,長さ
制約
- 入力に含まれる値は全て整数
解説
公式の解説はコチラ.今回もヤマカサさんのブログが非常に参考になりました.
mexってなんだ?
まず,問題文の
たとえば,以下の例題を考えると,
- 例1:
- 例2:
- 例3:
それぞれ,以下のようになります.
制約について考える
制約その1:
AtCoder では
制約その2:
この制約は問題を解く上で非常に重要かと思います.次節で集合
考え方詳細
問題の解法を詳細に考えていきます.
集合
ここで,
※このとき,制約その2があることによって,
たとえば,
図解するとこんな感じですね.
図は配列
さらに,
のとき, より のとき, より のとき, より
といった具合です.この例題の場合,答えは 0 です.
ソースコード
ステップ1:配列
ステップ2:
ステップ2の処理が少しむずかしいかもしれないので,ソースコードの意味を文章で説明します.実際の処理はソースコードを見てみてください.
さらに,更新後の
この更新を
ソースコードは以下のような感じです.問題文の添字は
#include <bits/stdc++.h>
#include <math.h>
#include <string>
using namespace std;
int main(void) {
int N, M;
cin >> N >> M;
vector<int> A(N, 0);
vector<int> B(N, 0);
for (int i=0; i<N; i++) {
cin >> A[i];
}
// step 1
for (int i=0; i<M; i++) {
B[A[i]]++;
}
int ans = N;
for (int i=0; i<N; i++) {
if (B[i] == 0) {
ans = i;
break;
}
}
// step 2
for (int i=0; i<N-M; i++) {
B[A[i]]--;
B[A[i+M]]++;
if (B[A[i]] == 0) {
ans = min(ans, A[i]);
}
}
cout << ans << endl;
return 0;
}
以下のサイトを参考に書いたので,かなりソースコードは似た感じに仕上がってしまいました.
まとめ
ちょっとトリッキーな最小値探索でした.一つずつ領域をずらしながら最小値を探索していくという類ですね.勉強になりました.
コメント