树状数组与线段树

树状数组与线段树

树状数组

看着这个视频学的。

想象一下,我们以这样的方式存储元素:把与a[i]之前的部分元素合存在我们的数组t[i]中,与a[i]无关的元素存在t[j]( j < i),这样,需要求前i个元素合时,需要用t[i]加上前j个元素合,而求取前j个元素就要用t[j]加上前面的无关元素,以此类推。是不是很像前缀合呢?确实很像,前缀和存储前面全部的元素,而树状数组存储部分元素,比起前缀合O(1)的时间得出区间合的优势,树状数组则需要O(logN)的时间,但是后者修改单个元素也只需要O(logN)的时间(稍后细索),稳定的时间是其最大的优势。

1. 前置知识

上面说了依照部分元素去存储,那怎么判断存储多少呢?LOW-BIT个元素。

简单的来说:low-bit,将一个数化为二进制后,最后一个1与后面的0构成其low-bit。

sample:

原数字 二进制 low-bit 十进制low-bit
1 01 1 1
2 10 10 2
5 101 1 1
8 1000 1000 8
7 111 1 1

有趣的是,low-bit存在快速计算方法,以5为例:

二进制:010,反码:101,反码加1:110,计算其low-bit只需二进制并反码加一

即:

\[lowbit(x) = x\&(-x) \]

2.原理

分成两种实现方式,前缀和与差分,前缀和用于单项修改,区间查找,差分用于区间修改、单项查找

前缀和

这里的前缀合是指t(n)存放的是若干的元素的合

我们需要两个操作:查找元素前缀和,单项修改。

首先是查找元素前缀和,假设数组t[n],对于其中元素t[i],存放它前low-bit个的元素和,需要使用时,递加减去low-bit的t[n]

//需要前x个数字的合
ans = 0
for(; x ; x -= lowbit(x))
	ans+=t[x]
return ans

//无非就是把前缀和分成logN个部分嘛

(先写到这儿)

posted @ 2021-09-21 16:02  seekerHeron  阅读(45)  评论(0)    收藏  举报