考前复习——树状数组
树状数组是一种支持 单点修改 和 区间查询 的,代码量小的数据结构。
什么是「单点修改」和「区间查询」?
假设有这样一道题:
已知一个数列 a,你需要进行下面两种操作:
给定 x, y,将 a[x] 自增 y。
给定 l, r,求解 a[l...r] 的和。
其中第一种操作就是「单点修改」,第二种操作就是「区间查询」。
点击查看代码
int n;
int a[N],c[N];//a[]:原数组 c[]:树状数组
inline int lowbit(int x)//返回最低位1 即树状数组c[]所代表的区间长度
{
return x&(-x);
}
int query(int u)
{
//a[1..u]之和
int ans=0;
for(int i=u;i>0;i-=lowbit(i))
ans+=c[i];
return ans;//请务必记得这个!!!
}
inline int interval(int l,int r)//区间和
{
return query(r)-query(l-1);
}
void single_update(int u,int w)
{
//单点修改:将u位置的值加上w
//修改被a[u]影响的所有的c[]
for(int i=0;i<=u;i+=lowbit(i))
c[i]+=w;
}
int main()
{
cin>>n;//输入节点数
for(int i=1;i<=n;i++)
{
cin>>a[i];
single_update(i,a[i]);//制作c[]
}
cout<<interval(1,n)<<endl;//输出1~n区间和
return 0;
}
若为矩阵 有如下代码
点击查看代码
void add(int x, int y, int v) {
for (int i = x; i <= n ;i += lowbit(i)) {
for (int j = y; j <= m; j += lowbit(j)) {
// 注意这里必须得建循环变量,不能像一维数组一样直接 while (x <= n) 了
c[i][j] += v;
}
}
}
int sum(int x, int y) {
int res = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
for (int j = y; j > 0; j -= lowbit(j)) {
res += c[i][j];
}
}
return res;
}
int ask(int x1, int y1, int x2, int y2) {
// 查询子矩阵和
return sum(x2, y2) - sum(x2, y1 - 1) - sum(x1 - 1, y2) + sum(x1 - 1, y1 - 1);
}
本文来自博客园,作者:pig_pig,转载请注明原文链接:https://www.cnblogs.com/pigAlg/p/17478302.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现