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)

posted @ 2022-07-23 21:51  云浅知处  阅读(52)  评论(0编辑  收藏  举报