https://codeforces.com/contest/1879/problem/D
关键在于互换两个 (\sum) 的顺序
一般像这样计算所有子区间的式子,如果要优化成接近线性,有一种可行思路是把注意力放在右端点,通过不断移动右端点,在移动的时候利用前面的统计结果算出移动右端点后的结果,从而得出所有子区间的答案。然后还有一个显然有用的套路是前缀和,这里记 $s_i=a_1 \oplus a_2\oplus ···\oplus a_{n-1}\oplus a_n $ ,(s_{i,j}) 为 (s_i) 二进制的第 (j) 位,我们会发现 (\sum_{l=1}{n}\sum_{r=l}{n}f(l,r)=\sum_{i=0}{32}\sum_{l=1}{n}\sum_{r=l}^{n}s_{l,i} \oplus s_{r,i}\times 2^i)
由于上面的式子可以优化成 (O(n\operatorname{log}V)),我们受到启发推出下面的式子
(\sum_{l=1}{n}\sum_{r=l}{n}f(l,r)\times(r-l+1))
(=\sum_{r=1}{n}\sum_{l=1}{r}f(l,r)\times(r-l+1)(调换∑位置))
(=\sum_{r=1}{n}\sum_{l=1}{r}\sum_{i=0}^{32} s_{l,i} \oplus s_{r,i}\times 2^i\times(r-l+1))
(=\sum_{r=1}{n}\sum_{i=0}{32} \sum_{l=1}^{r}[ s_{r,i}\oplus s_{l,i} =1]\times 2^i\times(r-l+1))
(=\sum_{r=1}{n}\sum_{i=0}{32} 2i\times\sum_{l=1}{r}([ s_{r,i}\oplus s_{l,i} =1]\times r-[ s_{r,i}\oplus s_{l,i} =1] \times (l-1)))
把 (r) 视作常量再观察上面的式子,你就会发现最后一维可以被优化掉,因为 $\displaystyle \sum_{l=1}^{r}[ s_{r,i}\oplus s_{l,i} =1]\times r $ 和 (\displaystyle \sum_{l=1}^{r}[ s_{r,i}\oplus s_{l,i} =1]\times (l-1)) 都可以预处理。
1 | void solve() |