当前位置: 首页 > news >正文

树状数组与线段树初步分析

  本篇只用于我对树状数组和线段树的初步思考记录

树状数组:

  对于tr[i],存储的是[i-(i&-i)+1,i]的数的信息。比如4的二进制为100,存储的就是[01,100]2的信息,6的二进制为110,存储的是[101,110]的信息。

  对于[1,r]范围的区间查询,用-=i&-i表示对r的二进制位全部分解,得到结果,如r=7时,二进制表示为111,则这段区间信息就是111的信息+110的信息+100的信息+000的信息,再如r=1012时,区间信息应为101+100+000,当r=1011时,区间信息为1011+1010+1000+0000

  对于[i]的单点修改,即让最低位1的位置不断提高以覆盖全部包含该数字的区间

  对于[l,r]的区间修改,由于树状数组的结构问题,必须将其转化为俩个单点修改,然后用前缀和求区间修改,这时就不便使用树状数组

所以树状数组用于简单的前缀和查询是比线段树要好很多的,但这里要注意的是,前缀和由于可以进行逆运算(sum[r]-sum[l-1]=sum[l,r])可以维护任意区间,但是最大值或者gcd是不支持右区间减左区间去维护任意[l,r]的范围,只能维护[1,r]的范围。因此,树状数组只能维护类似加法,异或,乘法(无0)的任意区间,对于最大值,最小值,gcd,lcm,之类的只能维护前缀信息。

  总结:树状数组本质上是维护前缀信息的结构。要查询任意区间 [ l , r ] 的信息,通常需要该信息满足可逆性(即可以通过两个前缀信息组合得到区间信息)。

单点修改代码如下:

  

查看代码
struct BIT {int n;vector<int> c;BIT(int n_) : n(n_ + 1), c(n_ + 1, 0) {}//初始化int sum(int r) {int s = 0;while (r > 0) s += c[r], r -= r & -r;return s;}//左区间查询int sum(int l, int r) {if (l > r) return 0;return sum(r) - sum(l - 1);}//区间查询void add(int idx, int delta) {while (idx < n) c[idx] += delta, idx += idx & -idx;}//点修
};

下标线段树:

  线段树是基于二分思想的一种数据结构,相对与树状数组,线段树可以通过懒标记来维护区间修改,以及区间信息,在功能上比树状数组要更胜一筹。

  线段树每个节点对应一个区间的汇总信息,因此要求区间之间满结合律。难点在于维护懒标记和区间合并的数学关系推导

  先看建树过程:

    可以用id<<1和id<<1|1这样朴素的建树方式,每个节点的结构体内变量l,r分别维护该节点表示的左右范围;

    也可以用动态开点的方式(n>=1e8),在函数的传递过程中传递区间l,r;

    以下是俩种建树方式的代码,可以自行比较

    

查看代码
void build(int id,int l,int r){tr[id]={l,r,a[l],1,0};if(l>=r)return;int md=(l+r)>>1;build(lc,l,md);build(rc,md+1,r);pushup(id);//这个地方如果不需要维护类似最值的条件就可以直接注释掉
}
/*
动态开点一般不会有建树函数,只有在用到的时候才会建节点,洛谷p13825模版题
*/
void add(int &id,int l,int r,int x,int y,int k){//if(!id)id=++idx;if(x<=l && r<=y){tr[id].sum+=k*(r-l+1);tr[id].add+=k;return;}pushdown(id,l,r);int md=(l+r)>>1;if(x<=md)add(lc,l,md,x,y,k);if(y>md)add(rc,md+1,r,x,y,k);pushup(id);
}
http://www.jsqmd.com/news/732610/

相关文章:

  • Kubernetes中AI代理自复制风险与防御策略
  • 2026名表维修避坑:网点搬迁≠服务升级,亨得利公示3个硬核标准才靠谱——积家/伯爵/宇舶维修只认六城直营,附官方地址与400热线 - 时光修表匠
  • 用ESP32的9个触摸引脚做个智能灯控?手把手教你玩转电容触摸感应(附Arduino代码)
  • 别再死记硬背CRC32公式了!用Python和Verilog双视角,手把手带你推导FPGA并行CRC电路
  • Draw.io本地部署指南:用开源版Diagrams搭建私有图表服务器,告别网络依赖
  • 2026深圳邀请赛F (SG函数+记忆化搜索)
  • 2026年5月亨得利官方声明公告:汉米尔顿/雪铁纳表主必存!正规服务点清单附7家直营门店地址与避坑建议 - 时光修表匠
  • 5月修表必看:别被“网点升级”忽悠!帝舵、浪琴表主都选这种店|亨得利直营门店地址与避坑指南 - 时光修表匠
  • 如何用 Python 快速接入 Taotoken 并调用多模型 API 服务
  • MCP 2026边缘部署性能优化(2024 Q3实测TOP3厂商对比:NVIDIA Jetson Orin vs. Qualcomm QCS6490 vs. 华为Atlas 200I DK)
  • 告别升级黑屏:为你的RK3588设备实现A/B无缝OTA(基于Android 12源码实战)
  • 从‘AttributeError’到成功运行:d2l包版本不匹配问题的完整诊断与修复指南
  • 开源IT资产管理系统深度解析:降低40%管理成本的完整解决方案
  • 智慧城市项目踩坑记:当城市坐标系(比如上海2000)遇上国家坐标系(CGCS2000)
  • 2025深度AI系统评估:方法论与关键技术解析
  • deepseek导出word手机 - DS随心转小程序
  • Modbus RTU通讯控制伺服电机全流程解析:从协议帧到AIMotor MD42实操避坑
  • 在 Claude Code 中配置使用 Taotoken 提供的 Anthropic 兼容通道
  • 别再浪费你的SD卡了!R2S固件刷写保姆级教程(附Rufus工具和固件下载)
  • 文本摘要技术:从Encoder-Decoder到工业实践
  • 终极Visual C++运行库修复指南:从问题诊断到自动化运维全攻略
  • 【MCP 2026安全漏洞实时修复白皮书】:2026年零日攻击防御体系首次公开,含3大自动热补丁引擎与FIPS 140-3验证路径
  • 5大技术突破重塑音乐歌词管理体验:163MusicLyrics开源工具深度解析
  • 终极免费法线贴图生成器:3步解锁专业3D质感
  • STM32F103/407芯片UID读取避坑大全:不同系列地址差异、字节序处理与常见编译错误解析
  • 如何永久保存你的数字记忆:WeChatMsg完全指南与个人AI训练方案
  • RAGLAB开源项目解析:从检索增强生成原理到工程实践全链路指南
  • 别再只会用Redis客户端了!手把手教你用Java Socket直接对话Redis服务端(RESP协议实战)
  • 如何用5个步骤获取全球金融数据?开源工具实战指南
  • 抖音视频批量下载终极指南:免费开源工具完整使用教程