ICode9

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

洛谷P3374树状数组题解--zhengjun

2022-06-10 18:39:03  阅读:127  来源: 互联网

标签:洛谷 树状 -- 题解 加上 父亲 减去 数组


数据结构之树状数组---zhengjun

P3374题目(树状数组1)

题目描述:

已知一个数列,你需要进行下面两种操作:

将某一个数加上 x

求出某区间每一个数的和

输入格式

第一行包含两个正整数 n,mn,m,分别表示该数列数字的个数和操作的总个数。

第二行包含 nn 个用空格分隔的整数,其中第 ii 个数字表示数列第 ii 项的初始值。

接下来 mm 行每行包含 33 个整数,表示一个操作,具体如下:

1 x k 含义:将第 x 个数加上 k

2 x y 含义:输出区间 [x,y] 的和

输出格式

输出包含若干行整数,即为所有操作 2 的结果。

输入输出样例
输入
5 5
1 5 4 2 3
1 1 3
2 2 5
1 3 -1
1 4 2
2 1 4
输出
14
16

树状数组的功能

树状数组,是一个查询修改的复杂度都为log(n)的数据结构。

	你或许还不理解,这玩意为什么长这样?那么,就用计算机的语言来解释吧(二进制)!

理解

重点来了

第一层:
      (0001)1的父亲是(0010)2;
      (0011)3的父亲是(0100)4;
      (0101)5的父亲是(0110)6;
      (0111)7的父亲是(1000)8;
       ————都以1结尾,并且都加上了1!!!
第二层:
      (0010)2的父亲是(0010)4;
      (0110)6的父亲是(1000)8;
       ————都以10结尾,并且都加上了10!!!
第三层:
      (0100)4的父亲是(1000)8;
       ————都以100结尾,并且都加上了100!!!

你一定找到规律了!

	在第几层,它的父亲就是加上1<<(层数-1);
	或者是,加上它最低位的一个1!
	那么,是不是又增加了复杂度呢?
	其实不是,只要一个简短的函数:
    #define lowbit(x) ((x)&(-x))

----------------没错!这就是树状数组的核心。

但是,区间求和时又该怎么办呢?

比如:要求1-7的和,就要分别加上 c[7] , c[6] , c[4] ;
我们研究一下这些数的二进制:

      0111--7
           减去1
      0110--6
           减去10
      0100--4
      	   减去100

每次减去的不正是当前编号的\(lowbit\)吗?

那么\(4\)再减,就变成了\(0\),只要一个\(while\)不就解决了吗?

问题

如果是\(4-7\)怎么办呢?

其实很简单:用\(1-7\)减去\(1-3\)不就可以了吗?

代码实现

用数组\(c\)来储存这棵树。

加值:

只需从它本身开始加,连续加上\(lowbit\)
来求它的父亲,并把它的父亲也加上这个值不就行了吗?

区间求和:

若要\(x-y\)的和;

分别用这两个数(\(x\)和\(y-1\))做一遍:

  用sum存储和,
  将sum加上当前的c[i];
  再减去lowbit(i)
  重复执行不就行了吗?(判断是否已减到0)

代码(未压行)

#include<cstdio>
#define maxn 500001
#define lowbit(x) ((x)&(-x))
#define read(n) scanf("%d",&n)//传说中的最牛的快读
int n,m;
int a[maxn],c[maxn];
void update(int rt,int x)
{
	while(rt<=n)
	{
		c[rt]+=x;
		rt+=lowbit(rt);
	}
	return;
}
int query(int rt)
{
	int sum=0;
	while(rt)
	{
		sum+=c[rt];
		rt-=lowbit(rt);
	}
	return sum;
}
int main()
{
	read(n),read(m);
	for(int i=1;i<=n;i++)
                read(a[i]),update(i,a[i]);//建树时只是将原来的0加上a[i]。
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		read(x),read(y),read(z);
		if(x==1)//修改
		{
			update(y,z);
		}
		else//查询
		{
			printf("%d\n",query(z)-query(y-1));
		}
	}
	return 0;
}

简单易懂,多好。

Thank you!

--------郑钧

标签:洛谷,树状,--,题解,加上,父亲,减去,数组
来源: https://www.cnblogs.com/A-zjzj/p/16364272.html

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

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

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

ICode9版权所有