No.284
最長部分門松列列を求める問題である.
は座標圧縮しておく.
まずは がすべて異なる場合を考える.
長さ が右端で, そのすぐ左側の長さが より大きい部分列の最大の長さを とし, 同様にすぐ左側の長さが より小さい部分列の最大の長さを とする.
そして を前から順に見ていくと,
となる. は最大値を計算する Segment Tree で管理すれば で計算できる.
さて, 実際は は同じ数値のものがあるので, そこをどうするか.
そこで, には [最大長, 自身の長さ, すぐ左側の長さ] をセットで保存するようにする. また, すぐ左側の長さが と同じ場合はそのセット使えないので, [2番目に大きい長さ, 自身の長さ, すぐ左側の長さ] のセットも保存するようにする.
そして, Segment Tree の最大値を計算する部分は, 最大長と2番目の長さを計算するようにする. このとき, 最大長とセットのすぐ左側の長さと2番目の長さとセットのすぐ左側の長さは異なるように計算する.
こうすることで, 最大長とセットすぐ左側の長さが と同じ長さの場合は2番目の長さを使えばいいことになる.
また, Segment Tree の更新であるが, 最大長は上記で取得したものを使う.上記で取得した自身の長さを除いて再度 Segment Tree に問い合わせる.