diverta 2019 Programming Contest E問題 : XOR Partitioning

問題. XOR Partitioning

数列  a = (a_1, \ldots, a_n) が与えられる. a の空でない連続部分列への分割で,その連続部分列のビットごとの排他的論理和がすべて等しくなるようなものが何通りあるかを求めよ.

制約 1 \le n \le 5 \times 10^5,  0 \le a_i < 2^{20}

解法.動的計画法

 a_1 を含む連続部分列を1つ固定すると,残りの分割で(ビットごとの)排他的論理和がとるべき値が一意に定まる.また,答えに寄与する分割内のすべての連続部分列の排他的論理和はすべて等しく,その値を  X として排他的論理和による累積和をとると前から  X, 0, X, 0, \ldots となり  X と 0 が繰り返されることが分かる.そこで, a排他的論理和による累積和を  b = (b_1, \ldots, b_n) とする. b_i = \oplus_{j = 1}^{i} a_j である.

上の考察から, b の要素を選択することと,ある連続部分列の右端として選択することを同一視すると, b から要素をいくつか選択して  (b_{i1}, b_{i2}, \ldots, b_{i k}) が条件を満たす分割であることは,この列が  (b_{i1}, 0, b_{i1}, 0, b_{i1}, \ldots, b_{i1}) または  (b_{i1}, 0, b_{i1}, 0, b_{i1}, \ldots, 0) となっていることである.先頭の要素の選び方は, b の要素の種類数なので  O(n) 通りあり,先頭の要素を決めたときの条件を満たす分割の仕方が何通りあるのかは動的計画法で求める.

動的計画法では, (X, 0, 0, 0, X, X, 0, 0, X, 0) のような列に対して,1番目と最後の要素は必ず選び, X と 0 が交互に現れる部分列の個数を求めている.ただし,最後が 0 でない場合は必ず最後の要素が  X でないとすべての要素を含む分割とならないので注意が必要である.
 X X の間にある 0 の個数は前もって計算することで各クエリに対して  O(1) 時間で求まる.また,考慮すべきこのような列の長さの総和は 0 を除くと高々  n しかないので,各列に対する動的計画法をその列の長さの線形時間で計算できれば全体も高速に計算可能である.

計算時間 O(n \log n)

通すので燃え尽きて説明が雑になったけどソースコードを見てもらえば.
計算時間が  O(n \log n) なのですが,累積和が等しい次の要素を求めるところや, X を固定したときの列を重複して求めない処理で mapset を使用せずに直接アドレス表を使用すれば  O(n) 時間で求まります.ただ, O(n \log n) でも通るので・・・.