数据结构

倍增

奇妙运用:求二进制下 \(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} \]

posted @ 2025-07-17 15:24  ask_silently  阅读(8)  评论(0)    收藏  举报