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

树状数组 线段树 笔记

写于 2023.11

树状数组

树状数组是维护 \(n\) 个数的前缀信息的一维数组。

其树型结构如下

这样的结构有着写法简单,常数小的特点。

其模板代码如下:

inline int lowbit(const int &x){//最后一个 '1' 对应的值 return x&-x;
}
void add(int pos,int val){//单点修改,将 a[pos] 的值增加 val while(pos<=n) t[pos]+=val,pos+=lowbit(pos);
}
int query(int pos){//查询[1,pos]的和 int sum=0;while(pos) sum+=t[pos],pos-=lowbit(pos);return sum;
}

除发挥其原本的前缀维护功能外( \(O(logn)\) 的前缀查询与单点修改),还可以用它来维护一个差分数组。这样,前缀和查询就变为了修改后的值的查询,弥补了差分数组只能“多次操作,一次查询”的短板。

将调用部分稍作修改即可完成 \(O(logn)\) 的区间修改与单点查询。

//此处t数组实际为一个差分数组
//[l,r]+val
add(l,val),add(r+1,-val);
//query: pos
printf("%d\n",query(pos));

其实,树状数组还可以方便地进行 \(O(logn)\) 的区间修改与前缀查询。

方法:对 query 与 add 函数进行修改,使其返回二次前缀和结果。

数学分析如下:

\[\begin{aligned} \sum^r_{i=l}\sum^i_{j=l} t_j &=\sum^r_{i=l}(r-i+1)\times t_i\\ &=\sum^r_{i=l}((r+1)\times t_i-i\times t_i)\\ &=(r+1)\times\sum^r_{i=l}t_i-\sum^r_{i=l}i\times t_i \end{aligned} \]

所以,我们可以维护两个树状数组,其意义分别为 \(t_i\)\(i\times t_i\) 的前缀。

代码如下:

int t1[maxn],t2[maxn];//t1为t的前缀,t2为i*t的前缀 
inline int lowbit(const int &x){return x&-x;}
void add(int pos,int val){int tem=pos;while(pos<=n) t1[pos]+=val,t2[pos]+=tem*val,pos+=lowbit(pos);
}
int query(int pos){int sum=0,tem=pos;while(pos) sum+=(tem+1)*t1[pos]-t2[pos],pos-=lowbit(pos);return sum;
}
void add_array(int l,int r,int val){add(l,val),add(r+1,-val);}
int query_array(int l,int r){return query(r)-query(l-1);}

简单包装为 class 可以有效增加代码的可读性。

inline int lowbit(const int &x){return x&-x;
}
class BIT{private:ll t[maxn];public:void add(int pos,ll val){for(int i=pos;i<=n;i+=lowbit(i)) t[i]+=val;}ll query(int pos){ll sum=0;for(int i=pos;i;i-=lowbit(i)) sum+=t[i];return sum;}
}

线段树

1 当不需要区间修改的线段树题目的做法

线段树是维护一个区间的树形结构。其维护的信息需要具有可加性(即通过组成大区间的两个小区间可以得到大区间的值)。

维护的信息具有可减性或其他可以使用树状数组的情况应用树状数组代替以获得更高的效率。

线段树的模板

struct node{int l,r;//other imformations
} t[4*maxn]; 
void pushup(node &u,node &l,node &r){//using l & r to make the new u//eg.//	u.val=l.val+r.val;
}
void build(int u,int l,int r){t[u]={l,r};if(l==r){// do something} else {int mid=l+r>>1;build(u<<1,l,mid),build(u<<1|1,mid+1,r);pushup(t[u],t[u<<1],t[u<<1|1]);}
}
void modify(int u,int pos,int val){if(t[u].l==t[u].r){// do modify} else {int mid=t[u].l+t[u].r>>1;if(pos<=mid) modity(u<<1,pos,val);else modify(u<<1|1,pos,val);pushup(t[u],t[u<<1],t[u<<1|1]);}
}
node query(int u,int l,int r){if(t[u].l>=l&&t[u].r<=r) return t[u];int mid=t[u].l+t[u].r>>1;if(r<=mid) return query(u<<1,l,r);else if(l>mid) return query(u<<1|1,l,r);node ans,ansl=query(u<<1,l,r),ansr=query(u<<1|1,l,r);pushup(ans,ansl,ansr);return ans;
}

此处 pushup 意为通过传入的后两个参数更新第一个位置的值,需要根据维护的具体信息修改。

build 的注释部分意为叶子结点的信息赋值,modify 的注释部分意为叶子结点的信息修改。这些部分均需要根据维护的信息改变。

有时维护的信息比较简单,query 可以不返回一整个结点,视题目而定。

http://www.rkmt.cn/news/61859.html

相关文章:

  • 大模型(LLM)基本原理
  • 实训(补)
  • 2025年下半年江苏网架、钢结构、光伏支架钢管、托辊钢管、汽车传动轴钢管厂家推荐指南:专业选择与权威解析
  • 2025年11月压力容器、化工设备、锅炉、换热器、反应釜厂家怎么选:前五推荐指南
  • 2025年下半年冷弯成型前冲孔生产线、C型钢自动抱焊机、钢结构码垛机、H钢冲孔液压设备、光伏支架冲孔机优质供应商推荐指南
  • 2025年下半年压力容器、化工设备、锅炉、换热器、反应釜厂家综合推荐指南:十大优质供应商深度解析
  • 从“人工寻宝”到“秒级解析”:文档信息抽取技术重塑保险保单处理流程
  • Swift相机功能实战:手把手教你实现扫码、拍照、视频录制全流程 - 指南
  • 全息投影仓的AI连接系统的开发代码要怎么写?
  • 2025年江苏储物柜、卧室套装、衣柜衣橱、厨房橱柜工厂、全屋定制源头厂家推荐榜单:十大专业厂家综合评测
  • VUE3基础环境搭建
  • 基于Halcon的相机图像采集系统设计与达成
  • 2025年下半年辣椒种子、色素椒种子、线椒种子、螺丝椒种子、加工型辣椒种子厂家推荐排行榜单:精选五家优质供应商指南
  • Python进阶学习
  • 2025年塑料托盘、塑胶卡板、吹塑托盘、塑料栈板、防渗漏托盘生产厂家选购全指南:品牌推荐与行业洞察
  • 2025年四川成都木瓜蛋白酶泡毛肚技术、毛肚蒸煮机、毛肚自动化设备、毛肚清洗机、毛肚加工设备、毛肚设备工厂综合评估与选购指南
  • 【图像算法 - 31】基于深度学习的太阳能板缺陷检测体系:YOLOv12 + UI界面 + 数据集建立
  • 2025年下半年仓储货架/冷库货架/AGV货架/CTU货架/大连货架厂家推荐榜单:十大专业供应商综合评测
  • 白井黑子
  • 2025年四川PRDP防腐式带立筋缠绕管公司排名
  • OKR 与 KPI
  • Windows后门工具排查_2025/11/26(持续更新)
  • 项目解决方案:轮船AI识别违规行为解决方案 - 教程
  • 实验4 组合与继承
  • 2025 西安口碑好的权威短视频拍摄运营公司推荐 3 家
  • 2025年下半年内蒙古通辽/赤峰/鄂尔多斯/包头/乌兰察布/呼伦贝尔/乌海/巴盟/阿拉善内蒙古房屋检测公司全方位挑选指南
  • ThingsBoard部件数据结构解析 - 教程
  • 【LVGL】表格部件
  • GeoJSON代码示例
  • 详细介绍:在 Ubuntu 系统中利用 conda 创建虚拟环境安装 sglang 大模型引擎的完整步骤、版本查看方法、启动指令及验证方式