数据结构
倍增
奇妙运用:求二进制下 \(1\) 的总个数,运用倍增的思想,先求出每两个之间的 \(1\) 的个数,然后是每四个最后到 \(64\) 或 \(32\) 位(当然可以用 STL 中的 __builtin_popcount)。
int popcount(int x){
x=(x&0x55555555)+((x>>1)&0x55555555);
x=(x&0x33333333)+((x>>2)&0x33333333);
x=(x&0x0F0F0F0F)+((x>>4)&0x0F0F0F0F);
x=(x&0x00FF00FF)+((x>>8)&0x00FF00FF);
x=(x&0x0000FFFF)+((x>>16)&0x0000FFFF);
return x
}
树状数组
奇妙运用:
区间加,区间求和。
\(d_i\) 表示差分数组,推一下式子:
\[\begin{aligned} \sum_{i=1}^r b_i &= \sum_{i=1}^r
a_i + \sum_{i=1}^r \sum_{j=1}^i d_j \\&= \sum_{i=1}^r a_i + \sum_{i=1}^r d_i \times (r-i+1) \\&= \sum_{i=1}^r a_i + \sum_{i=1}^r d_i \times (r+1) - \sum_{i=1}^r d_i \times i \end{aligned}\]
维护 \(d_i\) 前缀和和 \(d_i \times i\) 前缀和即可。
二维单点修改,区间查询。
只需拆成若干个 \(x\) 区间(每个 \(lowbit\) 管辖的区间)和若干个 \(y\) 区间即可。
二维前缀和考虑容斥即可。
二维区间修改,区间查询
\(d_{i,j}\) 表示差分数组,依旧来推一下式子:
\[\begin{aligned} \sum_{i=1}^a\sum_{j=1}^b &=\sum_{i=1}^a\sum_{j=1}^b\sum_{i1=1}^i\sum_{j1=1}^j d_{i,j} \\&= \sum_{i=1}^a\sum_{j=1}^b (a-i+1) \times (b-j+1) \times d_{i,j} \\&= \sum_{i=1}^a\sum_{j=1}^b (a+1)\times (b+1) \times d_{i,j} - \sum_{i=1}^a\sum_{j=1}^b (a+1) \times j \times d_{i,j} \\&- \sum_{i=1}^a\sum_{j=1}^b (b+1) \times i \times d_{i,j} + \sum_{i=1}^a\sum_{j=1}^b d_{i,j} \\&= (a+1)(b+1)\sum_{i=1}^a\sum_{j=1}^b d_{i,j} - (a+1)\sum_{i=1}^a\sum_{j=1}^b j \times d_{i,j} \\&- (b+1) \sum_{i=1}^a\sum_{j=1}^b i \times d_{i,j} + \sum_{i=1}^a\sum_{j=1}^b i \times j \times d_{i,j} \end{aligned}
\]

浙公网安备 33010602011771号