一.二维 单点修改,区间查询【最好学完树状数组的基本操作再来】

一维:

题意:

1 i x表示i位置+x, 2 i j表示i——j的所有数之和。

题解:

这是一道灰常简单的模拟题,首先将原数组改为树状数组,写好模板代码,碰到一个直接输处即可,注意输出i——j为闭区间,所以答案应为sum(i) - sum(j - 1),此处sum是前缀和。

代码:

#include <iostream>
#include <cstdio>
using namespace std;
int n, a[1000005], s, l, r, ww;
long long c[1000005];
int lowbit(int x) {
	return x & -x;
} 

void update(int k, int shu) {//更新/建树函数
	for(int i = k;i <= n; i+=lowbit(i)) {
		c[i] += shu;
	}
}

long long Sum(int zhong) {//求和
	long long da = 0;
	for(int i = zhong;i >= 1; i-=lowbit(i)) {
		da += c[i];
	}
	return da;
}
int main() {
	scanf("%d %d", &n, &s);
	for(int i = 1;i <= n; i++) {
		scanf("%d", &a[i]);
		update(i, a[i]);//建树
	}
	for(int i = 1;i <= s; i++) {
		scanf("%d", &ww);
		if(ww == 1) {
			scanf("%d %d", &l, &r);
			update(l, r);//更新
		}
		else {
			scanf("%d %d", &l, &r);
			printf("%lld\n", Sum(r) - Sum(l - 1));//求区间和
		}
	}
	return 0;
} 

二维:

题意:

1 i j x表示(i, j)位置+x, 2 a b c d表示求左下角为(a, b)右上角为(c, d)的子矩阵和

题解:

这道题和一维的差不多,但是首先要将树状数组整体变为二维,你可以想象得到,就是子节点选列,列又再选行就可以求得,当然他和一维的最大区别就是要考虑重复的情况,这有点类似于二维前缀和。
在这里插入图片描述

就比如这样一个图,我们将和考虑成面积,最后要求到 V V V绿那么即有:
V 绿 色 V绿色 V绿 = V 总 V总 V - ( V 蓝 V蓝 V + V 黄 V黄 V) - ( V 紫 V紫 V + V 黄 V黄 V) + V 黄 V黄 V
所以最后输出我们只需找点即可。

代码:

#include <iostream>
#include <cstdio>
using namespace std;
int n, m, flag, a, b, c, d;
long long BIT[10005][10005];

int lowbit(int x) {
	return x & (-x);
}

void update(int kx, int ky, int x) {
	for(int i = kx;i <= n; i += lowbit(i)) {
		for(int j = ky;j <= m; j += lowbit(j)) {
			BIT[i][j] += x;
		}
	}
}

long long Sum(int kx, int ky) {
	long long sum = 0;
	for(int i = kx;i > 0; i -= lowbit(i)) {
		for(int j = ky;j > 0; j -= lowbit(j)) {
			sum+=BIT[i][j];
		}
	}
	return sum;
}
int main() {
	scanf("%d %d", &n, &m);
	while(scanf("%d", &flag) != EOF) {
		if(flag == 1) {
			scanf("%d %d %d", &a, &b, &c);
			update(a, b, c);//修改 
			
		}
		else {
			scanf("%d %d %d %d", &a, &b, &c, &d);
			printf("%lld\n", Sum(c, d) + Sum(a - 1, b - 1) - Sum(a - 1, d) - Sum(c, b - 1));//类似于二位前缀和的做法,先将大矩形的算出来,再将多算的矩形去掉 
		}
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值