Codeforces Round #547 (Div. 3)F2. Same Sum Blocks (Hard)

問題概要

長さ n の数列 a_i が与えられる. この中から総和が等しい区間を複数選ぶとき, 最大でいくつ選べるか?(構築せよ. ) ただし区間同士が重なってはならないものとする.

問題へのリンク

制約

  •  1 \le n \le 1500
  •  -10^5 \le a_i \le 10^5

解説

数列の長さが短いので, 区間の数が比較的少なく, 区間和としてとりうる値を全列挙することができます. ただし, これらすべての値についてどう選ぶかを実装しようとすると O(n^4)O(n^2) 程度になってしまいうまくいきません.

そこで, std::map の key を区間和, value をその区間和をもつ区間 \{l, r\}vector として持ってみましょう. すると, 区間和を決めうったとき, 複数の区間からなる集合から重ならないようにたくさん選びましょうという問題になり, これは区間スケジューリング問題そのものです.

またこのように実装すると, ある区間についてたかだか 1 回しか見ることがないので, 全体としては O(n^2) 回しか見ません. ということで, ソートの分を含めて O(n^2\mathrm{log}n) で問題を解くことができました. 

実装

Submission #146489204 - Codeforces