ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

树状数组详解(区间修改和单点查询)

2021-08-07 19:30:29  阅读:178  来源: 互联网

标签:单点 树状 int 查询 修改 详解 数组 区间


前置芝士

单点修改和区间查询

引入

先看例题:(洛谷 P3368 【模板】树状数组 2

已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数数加上 x x x;
2.求出某一个数的值。

这题和 树状数组1 有什么区别?

没错,正如题目所说,这题是区间修改和单点查询

区间修改和单点查询

区间修改和单点查询要怎么实现呢?这需要用到一个东西:差分。

差分是什么呢?(知道的大佬可以跳过)

对于一个数组 a [ ] a[] a[],我们设它的差分数组为 b [ ] b[] b[],则满足:

b [ 1 ] = a [ 1 ] b[1]=a[1] b[1]=a[1]
b [ i ] = a [ i ] − a [ i − 1 ] ( 1 < i ≤ n ) b[i]=a[i]-a[i-1](1<i≤n) b[i]=a[i]−a[i−1](1<i≤n)

那这有什么用呢?我们可以发现一个性质:

a [ i ] = ∑ k = 1 n b k a[i]=\sum\limits_{k=1}^n b_k a[i]=k=1∑n​bk​

联系一下树状数组,你想到了什么?

对了!可以把单点查询转化为差分数组的区间查询!

那么区间修改又怎么解决呢?别着急,我们来看第二个性质:

我们设一个数组 a [ ] a[] a[]及它的差分数组 b [ ] b[] b[]为:

a [ ] a[] a[] 1 1 1 4 4 4 5 5 5 7 7 7 8 8 8 3 3 3 1 1 1
b [ ] b[] b[] 1 1 1 3 3 3 1 1 1 2 2 2 1 1 1 − 5 -5 −5 − 2 -2 −2

我们对 a [ ] a[] a[]进行区间修改,将 a [ 3 ] a[3] a[3]~ a [ 5 ] a[5] a[5]的值加上 2 2 2,可以得到:

a [ ] a[] a[] 1 1 1 4 4 4 7 7 7 9 9 9 10 10 10 3 3 3 1 1 1
b [ ] b[] b[] 1 1 1 3 3 3 3 3 3 2 2 2 1 1 1 − 7 -7 −7 − 2 -2 −2

观察 b [ ] b[] b[]的变化,你发现了什么?

只有 b [ 3 ] b[3] b[3]和 b [ 6 ] b[6] b[6]发生了变化! b [ 3 ] b[3] b[3]加上了 2 2 2, b [ 6 ] b[6] b[6]加上了 − 2 -2 −2!

经过多次试验,我们可以得到这样一个性质:

将 a [ l ] a[l] a[l]~ a [ r ] a[r] a[r]加上 k k k,等价于将 b [ l ] b[l] b[l]加上 k k k,将 b [ r + 1 ] b[r+1] b[r+1]加上 − k -k −k。

再联系一下树状数组,你又想到了什么?

我们可以将区间修改转化为差分数组的单点修改!

这样,我们就将区间修改和单点查询转化为了我们熟悉的单点修改和区间查询!问题迎刃而解了!

完整代码

#include<iostream>
#include<cstdio>
#define MAXN 500010
using namespace std;
int n,m,op,x,y,k;
int a[MAXN],c[MAXN];
int lowbit(int x)
{
	return x&(-x);
}
void update(int x,int k)
{
	for(;x<=n;x+=lowbit(x))
		c[x]+=k;
}
int query(int x)
{
	int res=0;
	for(;x>=1;x-=lowbit(x))
		res+=c[x];
	return res;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		update(i,a[i]-a[i-1]);
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&op);
		if(op==1)
		{
			scanf("%d%d%d",&x,&y,&k);
			update(x,k);
			update(y+1,-k);
		}
		else
		{
			scanf("%d",&x);
			printf("%d\n",query(x));
		}
	}
	return 0;
}

标签:单点,树状,int,查询,修改,详解,数组,区间
来源: https://blog.csdn.net/Wu_while/article/details/119491077

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有