ICPCアジア地区横浜大会2018 B問題 : Arithmetic Progressions

問題. Arithmetic Progressions

非負整数からなる集合  V = \{v_1, \ldots, v_n\} が与えられる. V の部分集合で等差数列となるものの中で要素数最大のものを見つけ,その要素数を答えよ.

制約 2 \le n \le 5000,  0 \le v_i \le 10^9

解法1

初めに, V を昇順にソートした列  (v'_1, \ldots, v'_n) を考える.次に,任意の  1 \le i < j \le n に対して,初項  v'_{i} で公差が  d = v'_{j} - v'_{i} の等差数列で左と右に極大なものを考える.左に極大とは  v'_{i} - d となる  V の要素が存在しなことであり,集合  Vstd::set で管理すると  O(\log n) 時間で判定できる.左が極大なものに対して, v'_{j} から順番に右に公差  d の要素が存在するかを  O(\log n) 時間で判定して,存在しなくなるまで繰り返すと右に極大な数列を得ることができる.このような等差数列の中で要素数最大のものが答えとなる.
極大な数列だけを考えているので,任意の  1 \le i < j \le n に対して, v'_{i}, v'_{j} の組は高々2回しか見ない.また, v'_{i}, v'_{j} のアクセスは定数時間か  O(\log n) 時間しかかからないので,全体で  O(n^2 \log n) 時間で答えを求めることができる.

計算時間 O(n^2 \log n)

解法2

解法1の高速化を考える.初項  v'_{i} で公差が  d = v'_{j} - v'_{i} の右に極大な等差数列を考えていたときに,nxt[i][j] = k ( v'_{k} = v'_{j} + d) という二次元配列があれば十分であることが分かる.なぜならば, v' の任意の等差部分数列  (v'_{i_1}, v'_{i_2}, \ldots, v'_{i_m}) と,任意の  1 \le j < m - 1 に対して,nxt[j][j + 1] = j + 2 となるからである.左に極大という条件も, v' の左から順番に初項の候補を探索していたので,nxt[i][j] は一度だけ使用可能とすれば満たされる.したがって,もし nxt[i][j] O(n^2) 時間で求めることができれば,答えも  O(n^2) 時間で求めることができる.実際,任意の  1 \le i  < j \le k \le n に対して,nxt[i][j] <= nxt[i][k] となり nxt[i] の値は単調増加するので,nxt[i] の値を  O(n) 時間で計算可能である.

計算時間 O(n^2)

まとめ

計算時間の見積もりが少し難しい