【ACWING】 线段树和树状数组
线段树可以说包含树状数组,树状数组往往代码短,运行效率非常高
线段树和树状数组,下标都从1开始存
一般优先考虑树状数组。
1 树状数组 O(logn)
1.1 用处
本质上只有这两种作用,可以结合其他方法创造出更多用途(比如区间修改和单点查询)。
- 动态地给某个位置上的数+一个数 (单点修改)
- logn时间复杂度内,动态地,快速求前缀和。 (区间查询)
树状数组就是这样的结构。
其原理简单来说,就是根据一个数的二进制表示,末尾有几个零,那么就在第几层
比如说,X = 4 =(100),那么就在第三层
反正,A数组中的奇数都会存在C中的第0层
设A是下标从1开始的原数组,C是树状数组,存的是一段A数组的和
比如第K
层的某个C数组C[x]
,他表示的范围是A数组中[x-2^k,x]
的和
也就是C[x] = A数组中(x-lowbit(x),x]的和
左开右闭
//返回一个二进制表示的最后一个1,即返回2^k int lowbit(int k){ return x & -x; }
1.2 具体实现
1. 单点增值
void add(int x, int v) { for(int i = x; i <= n; i += lowbit(i)) C[i] += v; } //单点修改 比如令某点等于v void add(int x, int v) { for(int i = x; i<=n; i+=lowbit(i)) C[i] = v - C[i]; }
2. 求前缀和
int query(int x) { int res = 0; for(int i = x; i; i-= lowbit(i)) res += C[i]; return res; } // 查某个区间[l ,r]和 query(y) - query(x - 1);
2 线段树
线段树是将一个数组,构造成树的形式。
线段树比较复杂,一般出现得很少,尤其是出现懒标记
的线段树,难度巨高
2.1 支持操作与复杂度分析
- 单点修改: O(logn)
- 区间查询: O(logn)
空间复杂度 O(4n),假设原数组长度为n,每个Node存储一个结构体
const int N = 10010; struct Node{ int l, r; int sum; }tr[N*4];
存储方式,和堆存储一样
// 设当前节点为为x 父节点为 tr[x>>1]; 左儿子;tr[x<<1]; 右儿子:tr[x<<1 | 1];
2.2 具体操作
带懒标记的线段树会多一个操作 push down
,我这里不包含这个
// push up函数,用子节点信息更新当前节点信息 void pushup(int u ) { tr[u].sum = tr[u<<1].sum + tr[u<<1 | 1].sum; }
//build 在一段区间上初始化线段树 // u为根节点编号,i,r是区间的左右边界 void build(int u, int l, int r) { // 如果是叶子节点 if(l == r) tr[u] = {l,r,w[l]}; // 如果不是叶子节点:二分+递归 else{ tr[u] = {l,r}; int mid = l + r >> 1; //注意 是求区间的中点 build(u<<1,l,mid), build(u<<1|1,mid+1,r); pushup(u); //更新节点信息 } }
//modify 修改 // u是根节点,x是目标值,v是增加的值 void modify(int u, int x, int v) { // 找到叶节点,更新 if(tr[u].l == tr[u].r) tr[u].sum += v; // 递归寻找目标值 else{ int mid = tr[u].l + tr[u].r >> 1; //注意是求tr[u]的中点,和build区分 if(x <= mid) modify(u << 1, x, v); ` else modify(u<<1 | 1, x, v); pushup(u); } }
// query 查询 int query(int u,int l, int r){ // 当前区间被完全包含了 if(tr[u].l >= l && tr[u].r <= r) return tr[u].sum; //递归算子区间 int mid = tr[u].l + tr[u].r >> 1; //注意是求tr[u]的中点,和build区分 int sum =0; // 如果左边有交集 if(l <= mid) sum += query(u<<1,l,r); //注意是小于等于,那么下面那个只能大于 if(r > mid) sum += query(u<<1 | 1, l, r); return sum; }
分类:
算法 / ACWING算法基础课
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步