一维树状数组模板

强推学习树状数组视频:完全理解并深入应用树状数组 | 支持多种动态维护区间操作
P3374 【模板】树状数组 1
P3368 【模板】树状数组 2

什么是树状数组

树状数组是用数组模拟树形结构

树状数组可以解决的问题

  • 单点修改
  • 区间修改
  • 区间查询
  • 区间修改

树状数组的优缺点

两者修改查询操作时间复杂度

操作朴素数组树状数组
单点修改1log2(n)
区间查询nlog2(n)
多次操作n^2nlog2(n)
  • 构建树状数组
for(int i = 1; i <= n; i++){
		scanf("%d", &a);
		add(i, a);
	}
  • 单点修改
void add(int x, int k){
	for( ; x <= n; x += x&-x){
		t[x] += k;
	}
}
e.g.
对第 i 个元素加K => add(i, k)
  • 区间查询
void add(int x, int k){
	for( ; x <= n; x += x&-x){
		t[x] += k;
	}
}
e.g.
查询[l, r]的和 => ask(r) - ask(l - 1)

对树状数组进行区间修改和单点查询是需要引入差分数组
-构建树状数组有些不同

for(int i = 1; i <= n; i++){
		scanf("%d", &a);
		add(i, a - ner);
		ner = a;
	}
  • 单点查询
e.g.
 查询l的值 => ask(l)
  • 区间修改
e.g. 
[l, r] + k => add(l, k); add(r + 1, -k)

P3374 【模板】树状数组 1

#include <cstdio>
using namespace std;
const int maxn = 5e5 + 5;
int n, m;
long long t[maxn];
void add(int x, int k){
	for( ; x <= n; x += x&-x){
		t[x] += k;
	}
}
long long ask(int x){
	long long ans = 0;
	for( ; x; x -= x&-x){
		ans += t[x];
	}
	return ans;
}
int main(){
	scanf("%d%d", &n, &m);
	int a;
	for(int i = 1; i <= n; i++){
		scanf("%d", &a);
		add(i, a);
	}
	int method, x, y, k;

	for(int i = 1; i <= m; i++){
		scanf("%d%d%d", &method, &x, &y);
		if(method == 1){	
			add(x, y);
		}
		else{
			printf("%ld\n", (ask(y) - ask(x - 1)));
		}
	}
	return 0;
}

P3368 【模板】树状数组 2

#include <cstdio>
using namespace std;
const int maxn = 5e5 + 5;
int n, m;
long long t[maxn];
void add(int x, int k){
	for( ; x <= n; x += x&-x){
		t[x] += k;
	}
}
long long ask(int x){
	long long ans = 0;
	for( ; x; x -= x&-x){
		ans += t[x];
	}
	return ans;
}
int main(){
	scanf("%d%d", &n, &m);
	
	int a, ner = 0;
	for(int i = 1; i <= n; i++){
		scanf("%d", &a);
		add(i, a - ner);
		ner = a;
	}
	
	int method, x, y, k;
	while(m--){
		scanf("%d", &method);
		if(method == 1){
			scanf("%d%d%d", &x, &y, &k);
			add(x, k);
			add(y + 1, -k);
		}
		else{
			scanf("%d", &x);
			printf("%d\n", ask(x));
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值