首页 > 其他分享 >【学习笔记】树状数组

【学习笔记】树状数组

时间:2023-09-10 21:23:47浏览次数:36  
标签:limits 树状 lowbit sum 笔记 数组 区间

PS:未经许可,禁止转载。思路来源于我的老师 $\text{hoogy}$,非常感谢,%%%。

- 五分钟丝滑动画讲解 | 树状数组

-〔manim | 算法 | 数据结构〕 完全理解并深入应用树状数组

单点修改,区间查询

前置芝士:

一维前缀和

设原数组 $a$,前缀和数组 $b$,则有:$b[i]=\sum\limits_{j=1}^ia[j]$。

推导,得 $b[i]=b[i-1]+a[i]$。
___________

设原数组 $a$,树状数组 $b$,其中 $b[i]=\sum\limits_{j=i-lowbit(i)+1}^ia[j]$,即 $b[i]$ 表示的是结尾位置为 $i$,长度为$lowbit(i)$的前缀和数组的和。

修改时,每次 $i+=lowbit(i)$,找到包含位置 $i$ 的所有区间,将 $b[i]+=k$,其中 $k$ 为修改值。

询问时,每次 $i-=lowbit(i)$,将 $s+=b[i]$,即:

$s=\sum\limits_{j=i-lowbit(i)+1}^ia[j]+\sum\limits_{j=i-lowbit(i)-lowbit(i-lowbit(i))+1}^{i-lowbit(i)}a[j]+\sum\limits_{j=i-lowbit(i)-lowbit(i-lowbit(i))-lowbit(i-lowbit(i-lowbit(i)))+1}^{i-lowbit(i)-lowbit(i-lowbit(i))}a[j]...=\sum\limits_{j=1}^ia[j]$
__________________
区间修改,单点查询
前置芝士:

一维差分

设原数组 $a$,差分数组 $d$,则有:$\sum\limits_{j=1}^id[j]=a[i]$。

推导,得 $d[i]=a[i]-a[i-1]$。
____________________
设原数组 $a$,树状数组 $b$,差分数组 $d$,其中 $b[i]=\sum\limits_{j=i-lowbit(i)+1}^id[j]$,即 $b[i]$ 表示的是结尾位置为 $i$,长度为$lowbit(i)$的差分数组和。

修改区间 $[l,r]$ 时,需修改两个点 $l,r+1$,即 $add(l,k),add(r+1,-k)$,其中 $k$ 为修改值,每次 $i+=lowbit(i)$,找到包含位置 $i$ 的所有区间,将 $b[i]+=k$,其中 $k$ 为修改值。

询问时,每次 $i-=lowbit(i)$,将 $s+=b[i]$,即:

$s=\sum\limits_{j=i-lowbit(i)+1}^id[j]+\sum\limits_{j=i-lowbit(i)-lowbit(i-lowbit(i))+1}^{i-lowbit(i)}d[j]+\sum\limits_{j=i-lowbit(i)-lowbit(i-lowbit(i))-lowbit(i-lowbit(i-lowbit(i)))+1}^{i-lowbit(i)-lowbit(i-lowbit(i))}d[j]...=\sum\limits_{j=1}^id[j]=a[i]$
__________________
区间修改,区间查询

要求用树状数组进行区间修改,区间查询。

设原数组$A$。

设差分数组$D$,其中$\sum\limits_{j=1}^iD_j=a_i$。

则有

$\sum\limits_{i=1}^n{\sum\limits_{j=1}^iD_j}=\sum\limits_{i=1}^nA_i\Rightarrow \sum\limits_{i=1}^nD_i\cdot(n-i+1)=\sum\limits_{i=1}^nA_i\Rightarrow \sum\limits_{i=1}^nD_i\cdot n-\sum\limits_{i=1}^nD_i\cdot (i-1)=\sum\limits_{i=1}^nA_i\Rightarrow n\cdot\sum\limits_{i=1}^nD_i-\sum\limits_{i=1}^nD_i\cdot (i-1)=\sum\limits_{i=1}^nA_i$


其中设$C_i=D_i$,$E_i=D_i\cdot (i-1)$

用树状数组维护数组 $C$ 和 $E$。

对于每次修改:

若修改区间 $[l,r]$,将此区间加 $x$,则$add(l,x),add(r+1,-x)$。

在 $add$ 函数中,即 $add(x,y)$,必须将位置 $x$ 保留下来,这样才能每个区间加上的数字一样,例如 $int$ $k=x$,将 $x$ 保留,因为 $x$ 在后面会进行变化。

遍历编号为 $i$ 的后面一个区间,即每次 $i+=lowbit(i)$。

根据公式

$C_i=D_i$,$E_i=D_i\cdot (i-1)$

每次将$C_i+=y$,$E_i+=y\cdot (k-1)$。

对于每次查询:

若查询区间 $[l,r]$,则输出$ask(r)-ask(l-1)$。

在 $ask$ 函数中,即 $ask(x)$ ,必须将位置 $x$ 保留下来,理由同上。

遍历编号为 $i$ 的前面一个区间,即每次 $i-=lowbit(i)$。

根据公式

$n\cdot\sum\limits_{i=1}^nD_i-\sum\limits_{i=1}^nD_i\cdot (i-1)=\sum\limits_{i=1}^nA_i$

每次将$s+=x\cdot C_i-E_i$。

练习:
_____________________________

[P6225 [eJOI2019] 异或橙子](https://www.luogu.com.cn/problem/P6225)

求区间 $[l,r]$ 的所有子区间的异或和。

找规律:

对于区间 $[1,2]$,$a_1⊕a_2⊕(a_1⊕a_2)=(a_1⊕a_1)⊕(a_2⊕a_2)=0$

对于区间 $[1,3]$ 原式,$a_1⊕a_2⊕a_3⊕(a_1⊕a_2)⊕(a_2⊕a_3)⊕(a_1⊕a_2⊕a_3)=(a_1⊕a_1⊕a_1)⊕(a_2⊕a_2⊕a_2⊕a_2)⊕(a_3⊕a_3⊕a_3)=a_1⊕a_3$

规律:

若 $l,r$ 同奇偶,则有异或和 $a_l⊕a_{l+1}⊕a_{l+2}⊕...⊕a_{r-1}⊕a_{r}$;

若 $l,r$ 一奇一偶,则有异或和为 $0$。

用树状数组维护奇数数组和偶数数组即可。

 

________________

P2880 [USACO07JAN] Balanced Lineup G

用树状数组维护区间 $[l,r]$ 的最值。

其中,修改时,应修改位置 $x$ 的每一个所属区间,将每个含有位置 $x$ 的区间都与修改值 $y$ 比一遍最值即可,注意,此题部分题解不正确,虽然能过此题,但是如果边询问边修改会出问题。
PS:最大值与最小值求法差不多。

在求区间 $[l,r]$ 的最值时,应每次判断 $r-lowbit(r)$ 是否大于等于 $l$,即查询当前的区间 $[r-lowbit(r)+1,r]$ 是否跨越区间 $[l,r]$,由于 $maxn(minn)[r]$ 表示区间 $[l,r]$ 的最值。

- 若跨越区间 $[l,r]$ 可能求不到正确的最值,于是往前一个找,即取 $min(a[r-1],askmax(min)(l,r-1))$。

- 若不跨越区间,则取 $min(maxn(minn)[r],askmax(min)(l,r-lowbit(r)))$。

- 特殊情况:若 $l=r$,则其区间最值为 $a[r](a[l])$。

____________________________

P5094 [USACO04OPEN] MooFest G 加强版

将所有奶牛按 $v_i$ 排序,此时其位置 $x_i$ 乱了,用两个树状数组分别维护 $x_i$ 位置之前元素的个数以及 $x_i$ 位置之前的累加和,推出柿子即可。


P4145 上帝造题的七分钟 2 / 花神游历各国

一道有思维的树状数组。

树状数组很容易想到,但并查集却比较难想,因为一个很大的数开多次方都会变得很小,但其小于等于 $1$ 时,对其开方就没有用了,于是记录即可。

__________________________

二维树状数组
______________________

单点修改,区间求值。

前置芝士:

二维前缀和
设原数组 $a$,前缀和数组 $b$,则有:$b[i][j]=\sum\limits_{k=1}^i{\sum\limits_{l=1}^ja[k][l]}$。

推导,得 $b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+a[i][j]$。
_____________________________________
使用二维前缀和的思想即可。
______________________________

区间修改,单点求值。

前置芝士:

 二维差分

设原数组 $a$,差分数组 $d$,则有:$\sum\limits_{k=1}^i{\sum\limits_{l=1}^jd[k][l]}=a[i][j]$。

推导,得 $d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]$。
____________________________________________

使用查分思想,每次 $update(x_1,y_1,k),update(x_2+1,y_2+1),update(x_1,y_2+1,-k),update(x_2+1,y_1,-k)$,即可。
____________________________________________
P4054 [JSOI2009] 计数问题

二维树状数组维护其前缀和,其中 $C[i][j][c]$表示前 $i$ 行 $j$ 列的颜色为 $c$ 的格子的数量,即可。

 


求逆序对

前置芝士:

逆序对

设原数组 $a$, 若有一对数 $(a[i],a[j])$,当且仅当 $i<j$ 且 $a[i]>a[j]$,则成这对数为逆序对。
________________________
暴力思想:

正向求解

正向遍历,每次将 $a[i]$ 插入到树状数组中,这里的树状数组就相当于一个桶,$ans+=i-sum(a[i])$,其中$sum(a[i])$ 为位置 $i$ 前所有小于等于 $i$的数字个数,而$i-sum(a[i])$ 为为位置 $i$ 前所有大于 $i$的数字个数,即满足逆序对的定义,就可以求出正确答案了。

逆向求解

逆向遍历,每次将$ans+=sum(a[i]-1)$,即位置 $i$ 后所有小于 $i$的数字个数,满足逆序对的定义,再将 $a[i]$ 插入树状数组之中。

- 警钟敲烂 在 $add$ 函数中 $i$ 的范围是 $\max(a[1],a[2],a[3],......,a[n])$,并不是 $n$。

离散化

以上方法只对于小数据起作用,一下方法讲解大数据方法。

由于$\max(a[1],a[2],a[3],......,a[n])$过大,数组装不下,离散化只需求出数组 $a$ 每个数的相对大小,例如:

| 1|
| -----------: |

| 原数组 | $147$ | $792$ | $283$ |
| :----------: | :----------: | :----------: | :----------: |
| 离散化数组 | $1$ | $3$ | $2$ |


但是,有时候会遇到数组元素相同的情况,例如:

| 原数组 | $283$ | $792$ | $283$ |
| :----------: | :----------: | :----------: | :----------: |
| 离散化数组 | $1$ | $3$ | $2$ |

逆序对数量与原来不相同。

尝试优化,可以进行如下改变:若 $a[i]=a[j]$,则 $a[i]$ 和 $a[j]$ 在离散化数组中的相对位置也相同,例如:

| 原数组 | $283$ | $792$ | $283$ |
| :----------: | :----------: | :----------: | :----------: |
| 离散化数组 | $1$ | $2$ | $1$ |

求出离散化数组中逆序对的个数,即求出了原数组中逆序对的个数。

二位树状数组之区间修改,区间查询

$sum_{n,m}=\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{k=1}^i\sum\limits_{l=1}^j d_{k,l}$

在矩阵 $[1,1]$ 到 $[n,m]$,推一下 $d_{k,l}$ 出现的次数,不难发现,$d_{k,l}$ 出现的次数为 $(n-k+1)\cdot(m-l+1)$。

例如,$d_{1,1}$ 在每个左上角为 $(1,1)$ 的矩阵都出现过,共出现 $n\cdot m$ 次。

于是将原式展开,有 $sum_{i,j}=\sum\limits_{i=1}^n\sum\limits_{j=1}^m d_{i,j}\cdot(n-i+1)\cdot(m-j+1)$

强拆后,得 $sum_{i,j}=\sum\limits_{i=1}^n\sum\limits_{j=1}^m d_{i,j}(nm-nj+n-mi+ij-i+m-j+1)$

整理,有 $sum_{i,j}=\sum\limits_{i=1}^n\sum\limits_{j=1}^m d_{i,j}((nm+n+m+1)-i(m+1)-j(n+1)+ij)$

于是 $sum_{i,j}=\sum\limits_{i=1}^n\sum\limits_{j=1}^m d_{i,j}(nm+n+m+1)-d_{i,j}i(m+1)-d_{i,j}j(n+1)+d_{i,j}ij$

显然,在这里要维护四个树状数组:$d_{i,j},d_{i,j}i,d_{i,j}j,d_{i,j}ij$。

P4514 上帝造题的七分钟

标签:limits,树状,lowbit,sum,笔记,数组,区间
From: https://www.cnblogs.com/CSP-AK-zyz/p/17691960.html

相关文章

  • 【学习笔记】【自学】【模板】矩阵快速幂
    题目描述:给定$n\timesn$的矩阵$A$,求$A^k$。矩阵:一个$m\timesn$的矩阵是一个由$m$行$n$列元素排列成的矩形阵列。即形如$$A=\begin{bmatrix}a_{11}&a_{12}&\cdots&a_{1n}\\a_{21}&a_{22}&\cdots&a_{2n}\\\vdots&\vdots&......
  • 密码协议学习笔记(4):比特承诺
    比特承诺:股票经纪人甲试图说服乙购买他的服务,甲表示,它已分析出若干支股票将会涨停,但在乙出钱购买它的服务之前,它不能透露如此有价值的信息,于是甲将这几支股票写在纸上,并锁进保险箱里,将保险箱交给乙,表示,一个月后将钥匙给乙,如果到时候打开保险柜,看看里面写的股票是否确......
  • 【学习笔记】【自学】【模板】三分法
    题目描述:给定一个$n$次函数$f(x)$形如$a_1x^n+a_{2}x^{n-1}+......+a_{n-1}x^2+a_nx+a_{n+1}$,求$f(x)_{\max}$,且$x\in[l,r]$,设使得$f(x)_{\max}$的$x$为$x_{\max}$。对于一个区间$[l,r]$而言,若确定使得$f(x)$为最大值的$x$定在$[l,r]$中,则可以使用三分法求......
  • 【学习笔记】P8590 『JROI-8』这是新历的朝阳,也是旧历的残阳
    比较有思维的一个数学题,写个笔记纪念一下。显然,为了使$\sum\limits_{i=1}^na_i^2$最大,整数一定要放最后一段,即求$\sum\limits_{i=1}^n(a_i+m)^2$,而负数需要分情况考虑,即放第一段还是最后一段,中间的$m-2$是空段,只考虑$1$和$m$这两个极端情况。可以设中间节点$t$,$a_{i......
  • 【学习笔记】【自学】三维偏序 (CDQ)
    [P3810【模板】三维偏序(陌上花开)](https://www.luogu.com.cn/problem/P3810)题目描述:有$n$个元素,第$i$个元素有$a_i,b_i,c_i$三个属性,设$f(i)$表示满足$a_j\leqa_i$且$b_j\leqb_i$且$c_j\leqc_i$且$j\nei$的$j$的数量。对于$d\in......
  • Linux教材第一、二章学习笔记及遇到的问题
     第一章第一章主要学习了unix、Linux的特性、文件系统组织、系统管理等内容。UbuntuLinux的特性出于安全原因,要运行任何特权命令时,用户必须输入sudocommand,首先会验证用户的密码。 Unix/Linux文件系统组织目录的查看,创建,增加,删除 手册页的查看。 UbuntuLinux......
  • 20211312徐元琦 学习笔记1
    历史:Unix是早期的商业化操作系统,诞生于20世纪60年代,最早由AT&T的贝尔实验室开发。它的设计目标是支持多用户和多任务的环境。Linux是由LinusTorvalds于1991年创建的开源操作系统。它最初是为个人计算机而开发,后来演变成一个广泛的操作系统家族。联系:Linux是基于Unix的设计,因......
  • 读书笔记1
    读书笔记120211215卢泽第一章-引言1.1系统编程的作用系统编程的目标是有效地利用系统资源来开发应用软件,并为学生提供扎实的专业基础。1.2本书目标本书旨在强化学生的编程背景知识,并涵盖了以下主题:动态数据结构的应用进程概念和进程管理并发编程定时器和定时功......
  • python学习笔记-redis缓存数据库
    一、缓存数据库介绍NoSQL(notonlysql)redis是业界主流的Key-valuenosql数据库之一,和memcached类似redis优点:速度快,每秒可执行大约110000设置操作,81000个/每秒的读取操作支持丰富的数据类型,列表,结合,可排序集合,哈希等操作是原子的二、redis操作安装redisubuntu安装$......
  • 20211316郭佳昊 《信息安全系统设计与实现(上)》学习笔记1
    一、任务要求[1]知识点归纳以及自己最有收获的内容,选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容(4分)我在学***X知识点,请你以苏格拉底的方式对我进行提问,一次一个问题核心是要求GPT:请你以苏格拉底的方式对我进行提问然后GPT就......