当前位置:网站首页>树状数组模版+例题
树状数组模版+例题
2022-08-05 08:11:00 【9ack!?】
简介
树状数组是一种维护区间和的数据结构,支持单点查询。经过魔改后也可以进行区间修改-单点查询, 区间修改-区间查询。你问为什么没有单点修改, 单点查询?因为数组就可以解决了哈哈。
我这里就不介绍原理了,网上一搜一大把。
基本树状数组
const int maxn = 100;
int a[maxn+5]; // 存放原始数据
int c[maxn+5]; // 存放树状数组
int n; // 存放数据的最大下标
int lowbit(int x) {
return x&(-x);
}
void add(int i, int k) {
while(i <= n) {
c[i] += k;
i += lowbit(i);
}
}
int getsum(int i) {
// 计算从1开始到i(两边都是闭区间)的区间和
int res = 0;
while(i > 0) {
res += c[i];
i -= lowbit(i);
}
}
void init() {
// 创建树的时候调用
for(int i = 1; i <= n; ++i) {
c[i] += a[i];
int j = i + lowbit(i);
if( j <= n) c[j] += c[i];
}
}
// 查询[x, y]
int sum = getsum(y)-getsum(x-1);
区间修改, 单点查询
首先不能直接套用上面的模版,对区间内的每个元素进行单点修改时间复杂度肯定会爆。
思考一下对区间进行修改时的特点,对整个区间进行修改的时候,区间内相邻元素的差值是不变的,所以我们可以用树状数组维护原数组的差分数组,修改的时候只需要对区间的两个端点修改即可。查询某个点的值时,求出差分数组的前缀和即可。
// 这里的函数直接套用上面的模版即可
// [x, y]区间加上k
for(int i = 1; i <= n; ++i) {
// 读入数据
scanf("%d", &a[i]);
update(i, a[i]-a[i-1]);
}
// [x, y]区间加上k
update(x, k);
update(y+1, -k);
int sum = getsum(i); // 这里的getsum变成了对差分数组的前i个元素进行求和, 于是得到的是a[i]
区间修改, 区间查询
这个就更玄学了,这个问题完全可以用线段树来解决,而且明显树状数组能维护的信息不如线段树多。但是线段树的常数要比线段树小,所以在某些条件下还是能解决一些问题的 (就比如下面的例题)
实际代码模版也差不多,但是运用了更加神奇的方法
// 需要维护两个树状数组
const int maxn;
int n, m;
int a[maxn];
int sum1[maxn]; // (D[1] + D[2] + ... D[n]), D是差分数组
int sum2[maxn]; // (1*D[1] + 2*D[2] + .. + n*D[n])
void update(int i, int k) {
int x = i;
while(i <= n) {
sum1[i] += k;
sum2[i] += k*(x-1);
i += lowbit(i);
}
}
int getsum(int i) {
int res = 0, x = i;
while(i > 0) {
res += x*sum1[i] - sum2[i];
i -= lowbit(i);
}
return res;
}
// 读入数据
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
update(i, a[i]-a[i-1]);
}
// [x, y]区间加上k
update(x, k);
update(y+1, -k);
// 求[x, y]区间和
int sum = getsum(y) - getsum(x-1);
//连这一篇都要限流...
边栏推荐
- Thinking after writing a code with a very high CPU usage
- 在ASP控制数字及字母输入
- 力扣刷题八月第一天
- SVG big fish eat small fish animation js special effects
- Access Denied: "microsoft.web.ui.webcontrols" workaround
- 行走社会100绝招
- CROS and JSONP configuration
- 利用Jenkins的持续集成
- What is the connection and difference between software system testing and acceptance testing? Professional software testing solution recommendation
- 最 Cool 的 Kubernetes 网络方案 Cilium 入门教程
猜你喜欢
ps怎么把图片变清晰,自学ps软件photoshop2022,简单快速用ps让照片更清晰更有质感
php向mysql写入数据失败
Fiddler工具讲解
嵌入式系统:基本定时器
【结构体内功修炼】结构体内存对齐(一)
SVG Star Wars Style Toggle Toggle Button
Vulnhub target drone: HA_ NARAK
v-if/v-else根据计算判断是否显示
MySQL database error The server quit without updating PID file (/var/lib/mysql/localhost.localdomain.pid)
Adb authorization process analysis
随机推荐
ps怎么把图片变清晰,自学ps软件photoshop2022,简单快速用ps让照片更清晰更有质感
Codeforce 8.1-8.7做题记录
双向循环带头链表
小本创业者的致胜法宝!
【结构体内功修炼】枚举和联合的奥秘(三)
8.4 Summary of the mock competition
数据源对象管理Druid和c3p0
Detailed explanation of DNS query principle
Nn. Unfold and nn. The fold
egg框架中解决跨域的三种方案
达梦数据库大表添加字段
Data source object management Druid and c3p0
ps怎么拼图,自学ps软件photoshop2022,PS制作拼图效果
链表专项之环形链表
8.4模拟赛总结
RedisTemplate: 报错template not initialized; call afterPropertiesSet() before using it
v-if/v-else determines whether to display according to the calculation
SQL SERVER关于主从表触发器设计
uniapp时间组件封装年-月-日-时-分-秒
长期招聘嵌入式开发-深圳宝安