2022.7.23 做题记录
Luogu3760 TJOI2017 异或和 Future 7.5
给定长为 \(n\) 的序列 \(a\),求其所有子区间和的异或值。\(1\le n\le 10^5,1\le \sum a_i\le 10^6\)。
一眼看过去不太会做,瞄了眼标签发现是「树状数组」突然就会了......
考虑算出来前缀和 \(S_i=\sum_{j=1}^ia_j\),那么区间和就是 \(S_i-S_{j-1}\),并且 \(1\le S_i\le 10^6\)。
然后我们枚举 \(S_i\),考虑算 \(\bigoplus_{j=0}^{i-1}(S_i-S_j)\),其中 \(\oplus\) 表示异或。
考虑枚举第 \(r\) 位,算出来有多少 \(S_i-S_j\) 第 \(r\) 位为 \(1\)。
注意到,一个数 \(x\) 的第 \(r\) 位为 \(1\),相当于 \(x\bmod 2^{r+1}\ge 2^r\)。
我们考虑开 \(O(\log V)\) 个树状数组,第 \(r\) 个树状数组里面存所有 \(S_j\bmod 2^{r+1}\) 的值,分类讨论一下:
- 对于 \(S_j\bmod 2^{r+1}\le S_i\bmod 2^{r+1}\) 的 \(j\),需要有 \(S_i\bmod 2^{r+1}-2^r\ge S_j\bmod 2^{r+1}\)。
- 对于 \(S_j\bmod 2^{r+1}>S_i\bmod 2^{r+1}\) 的 \(j\),需要有 \(S_i\bmod 2^{r+1}+2^{r}\ge S_j\bmod 2^{r+1}\)。
用树状数组维护单点加与区间和即可。时间复杂度 \(O(n\log^2 V)\)。AC Code
然后你发现其实只需要算出来 \(c_i\) 表示区间和为 \(i\) 的区间个数,这个可以直接 FFT 于是 1log 做法就有啦
晚上打了场 abc,见 AtCoder Beginner Contest 261 (C~F)