首页 > 其他分享 >树状数组

树状数组

时间:2023-08-12 22:57:32浏览次数:26  
标签:... limits 树状 int lowbit sum rs 数组

前置知识:lowbit运算

\(lowbit(x)\) 表示正整数 \(x\) 在二进制表示下最低位的 \(1\) 跟后面的 \(0\) 构成的数值 ,有 \(lowbit(x)=x\) & $ ($ ~\(~x+1)\) ,即 \(lowbit(x)=x\) & \(-x\),理由如下:

\(lowbit(x)\) 是最后一位 \(1\) 所以跟前面的位没啥关系,祂在二进制表示下肯定就是 \(1\) 跟上很多 \(0\), 我们将 \(lowbit(x)\) 所在位跟后面拿出来看,毋庸置疑整出来就是 \(lowbit(x)\)

x    : 1 0 0 ... 0 0
~x   : 0 1 1 ... 1 1
~x+1  : 1 0 0 ... 0 0

再说前面的位,每一位肯定是 \(0\) & \(1=0\) 或者 \(1\) & \(0=0\),对答案没有影响,不用理祂


模板

维护一个数组 \(a\) 的两种操作

  • \(a_x\gets a_x+k\)

  • 查询 \(\sum\limits_{i=l}^ra_i\)

对于第二个操作,转换一波 \(\sum\limits_{i=l}^ra_i=\sum\limits_{i=1}^ra_i-\sum\limits_{i=1}^{l-1}a_i\) ,变成维护前缀和


BIT

搞一波 $t_x=\sum\limits_{i=x-lowbit(x)+1}^xa_i $,说白了就是用 \(t_x\) 表示以 \(x\) 结尾的长度为 \(lowbit(x)\) 的区间和啊,配上图就变得神奇了,因为祂是一棵树:

magic

对于这棵树,有以下性质

  • \(t_x\) 表示区间长度为 \(lowbit(x)\)

  • \(x\) 的父节点是 \(x+lowbit(x)\) 即 \(x\) 的子节点是 \(x-lowbit(x)\)

  • 树的深度是 \(\log_2n\)


前缀和

考虑查询前缀和 \(\sum\limits_{i=1}^xa_i\) ,根据定义,可以把祂分段搞了,即

\[\sum\limits_{i=1}^xa_i=t_x+\sum\limits_{i=1}^{x-lowbit(x)}a_i \]

套娃之后可以递归或者循环求掉

int ask(int x) {
	int rs=0;
	for( ; x; x-=x&-x) rs+=tr[x];
	return rs;
} 

单点加

考虑单点加操作,观察图,显然与 \(a_x\) 有关的有且仅有 \(x\) 所在那条链,根据上述性质,珂以得出找父节点的办法,就这样一直加上去就珂啦

void add(int x,int w)
	{ for( ; x<=MAXN; x+=x&-x) tr[x]+=w; } 

其中 \(MAXN\) 是上界


理解

本质上是二分(?),此外类似的可以维护最大值

标签:...,limits,树状,int,lowbit,sum,rs,数组
From: https://www.cnblogs.com/chelsyqwq/p/17625742.html

相关文章

  • 链表和数组的区别
    链表和数组的区别链表逻辑上相邻的元素在物理位置上不一定相邻。优点:插入、删除效率高,不需要一个连续的很大的内存缺点:查找某一个位置的元素效率低。数组优点:存取速度快缺点:1.整块连续空间,占很大内存。2.插入或删除数据效率低、不方便链表数组逻辑上相......
  • 随笔-C-指针数组使用简记
    typedefstructmem_list*cns_detail_encode_result[encode_type_max];(gdb)p&((structmem_list**)0x7fffb4557950)[0]#&取对应点的位置$29=(structmem_list**)0x7fffb4557950(gdb)p((structmem_list**)0x7fffb4557950)+0$30=(structmem_list**)......
  • 【蓝桥杯备赛系列 | 简单题】数组排序(八大排序演示)
    ......
  • 找出数组中两个数的和等于给定目标值
    注意,输出的是数在列表中的索引,所以组织字典时用这个结构{list_value:list_index}deftwo_sum(nums,target):num_dict={}fori,numinenumerate(nums):complement=target-numifcomplementinnum_dict:return[num_dict[comp......
  • 数组方法slice使用
    目录前言导语代码部分总结前言我是歌谣歌谣的意志是永恒的放弃很容易但是坚持一定很酷导语数组方法slice使用编辑代码部分```varfangfang=["geyao","fangfang","huahua","mingming"]//arr.slice([begin[,end]])varfangfangTest=fangfang.slice(1)//从第一位进行截取cons......
  • 认识Javascript数组
    1.认识数组 数组就是某类数据的集合,数据类型可以是整型、字符串、甚至是对象Javascript不支持多维数组,但是因为数组里面可以包含对象(数组也是一个对象),所以数组可以通过相互嵌套实现类似多维数组的功能 1.1定义数组声明有10个元素的数组vara=newArray(10此时为a已经......
  • Leetcode 977. 有序数组的平方(Squares of a sorted array)
    题目链接给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序.示例1:输入:nums=[-4,-1,0,3,10]输出:[0,1,9,16,100]解释:平方后,数组变为[16,1,0,9,100]排序后,数组变为[0,1,9,16,100]示例2:输入:nums=[-7,-3,2,3,11]输......
  • Go数组转换,[]byte、[]unint16互相转换的方法封装,完整范例
    需求:分别封装方法将[]byte转换成[]unint16,将[]unint16转换成[]bytebyte相当于unint8分析:长度为20的[]byte转换为长度为10的[]unint16,他们之间的转换如bytes:=[]byte{0,1}  ===》[0*256+1]=1 注意:第奇数乘256加偶数的值则[]uint16的值为[1]完整代码如下:1pack......
  • C++使用Py*调用Python3模块中类成员函数及数组参数传递
    1.首先来看Python模块的部分结构和代码。ssd_network_classify.py文件中有SSD_Network_Classify类及其识别的成员函数detect_image(),返回值是一个1维的不定长double型数组。classSSD_Network_Classify:#其他函数实现省略。。。defdetect_image(sel......
  • JSON数据压缩传输(一)- 无标记数组
    服务端string[]fields=dto.fields.Split(',');varresluts=newList<dynamic>();//只取前端使用的字段foreach(varitemindata){varobj=newSystem.Dynamic.ExpandoObject()asIDictionary<string,Object>;foreach(varfieldinfields){......