H - Guess the Sum Editorial by Kiri8128

O(N) 解法

簡単のため、問題文の\(R\) には \(1\) を加えておきます。 半開区間 \([2^i\cdot j,\ 2^i\cdot (j+1))\) をなるべく少ない個数だけ組み合わせて \([L, R)\) を作れるかという問題です。 ただし組み合わせる際には、加算操作と減算操作ができるものとします。

\(L\)\(R\) の LSB (Least Significant Bit)の小さい方を \(j_0\) とすると、 \(j < j_0\) のクエリを投げる必要はないことが分かります。 また \(j=j_0\) のクエリとして考える必要があるものは高々 4 つであることが分かります。具体的には \(L\) の最小ビットの値(LSB が \(2^k\) の位に立っていたら \(k\) でなく \(2^k\) を表す)を \(a\)\(R\) の最小ビットを \(b\) とすると考える必要があるものは高々次の \(4\) つです。

  • \([L - a, L)\)
  • \([L, L + a)\)
  • \([R - b, R)\)
  • \([R, R + b)\)

\(a<b\) のときは後半ふたつは不要で、\(a>b\) のときは前半ふたつは不要です。これにより、 \(O(1)\) で LSB が真に大きくなる半開区間に帰着することができます。 LSB を大きくしていくにつれて帰着される区間の個数が爆発的に増えないかが心配になりますが、可能性があるのは各 \(j\) について \(L\)\(R\) それぞれから左右に最も近い点のみであるので、各 \(j\) について高々 \(4\) 個 です。

以上より全体の計算量 \(O(N)\) で問題を解くことができます。

posted:
last update: