首页 > 编程语言 >提高组算法-树状数组

提高组算法-树状数组

时间:2024-02-25 15:56:14浏览次数:19  
标签:数字 树状 int lowbit 查询 算法 数组

树状数组是当序列动态变化时,依然可以高效率的查询和维护前缀和(或区间和)的数据结构。

实现思路

现在有 \(16\) 个数字:\(a[]={1,8,5,9,6,3,9,8,7,2,3,9,6,4,1,7}\)。

我们要实现 \(2\) 个函数:

  1. 修改其中某个元素的数值。

  2. 求出前 \(n\) 个数字的和。

但是,这 \(2\) 个函数要在极短的时间限制内解决数百万个以上操作。那该如何编写呢?


我们先从最原始的方法开始想:用 \(a\) 数组把数字存储,每次查询就遍历一遍。但是这样查询会非常的慢,可能运行到明年都运行不完。

那我们可以这样想:
把 \(a\) 数组的元素两两求和放入第 \(2\) 层,这样我们查询速度会快很多,每次也只需要多修改一个数字。照此方法:我们再把 第 \(2\) 层的元素两两求和,放入第 \(3\) 层。把 第 \(3\) 层的元素两两求和,放入第 \(4\) 层。以此类推。直到只剩 \(1\) 个元素为止。

如果要计算前 \(7\) 个数字的和,也只需要计算成 \(23+9+9\) 就可以了,大大的加快了计算的速度。

但我们观察这个表,会发现许多数字根本不会用到!

例如:数字 \(14\),在计算前 \(3\) 个数字和直接 \(9+5\);在计算前 \(4\) 个数字的和直接用 \(23\);在计算前 \(5\) 个数字的和直接用 \(23+6\)。所以数字 \(14\) 根本就不需要使用,但想这样没用的数字还有很多。

所有层的第偶数个数字都是无用的,去掉了也不影响计算。即变成这个样子:

我们数一下数量,会发现,在这个表中剩下的数据刚好是 \(16\) 个。我们可以把这些数字都存储在数组 \(b\) 中,这个数组就是树状数组。

如上图,\(b[]={1,9,5,23,6,9,9,49,7,9,3,21,6,10,1,88}\)(按照后序遍历存储)

求和时,我们只要找到对应的区间并相加就可得出结果。

修改时,我们只需要向上找到包含他的区间进行修改即可。

听着很复杂,但他们的实现其实只要 \(10\) 行不到,那要具体实现他们,我们先来了解一下 lowbit 函数。

lowbit 函数

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

会求出数字 \(x\) 的二进制中最低位代表哪一个数字。

例如:\(x=70\),将 \(x\) 转换为二进制是 \(1000110\),他的最后一个 \(1\) 代表 \(2\),所以 \(70\) 的 lowbit 就是 \(2\)。

第一层的区间长度为 \(1\),而他们的 lowbit 也为 \(1\)。第二层的区间长度为 \(2\),而他们的 lowbit 也为 \(2\)。其他也是这样以此类推。序号为 \(i\) 的序列正好就是长度为 \(lowbit(i)\) 且以 \(i\) 结尾的序列。

还有一个性质,就是序列 \(b[i]\) 正上方的序列,正好就是 \(b[i+lowbit(i)]\)。

inline void add(int p,int x)
{
	while(p<=n)
	{
		b[p]+=x;
		p+=lowbit(p);
	}
}
inline int sum(int x)
{
	int ans=0;
	while(x>0)
	{
		ans+=b[x];
		x-=lowbit(x);
	}
	return ans;
}

单点修改+区间查询

P3374 【模板】树状数组 1

#include <bits/stdc++.h>
using namespace std;
int n,b[500005],m;
inline int lowbit(int x)
{
	return x&(-x);
}
inline void add(int p,int x)
{
	while(p<=n)
	{
		b[p]+=x;
		p+=lowbit(p);
	}
}
inline int sum(int x)
{
	int ans=0;
	while(x>0)
	{
		ans+=b[x];
		x-=lowbit(x);
	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		int x;
		cin>>x;
		add(i,x);
	}
	while(m--)
	{
		int op,x,y;
		cin>>op>>x>>y;
		if(op==1)
		{	
			add(x,y);
		}
		else if(op==2)
		{
			cout << sum(y)-sum(x-1) << endl;
		}
	}



	return 0;
}

区间修改+单点查询

P3368 【模板】树状数组 2

标签:数字,树状,int,lowbit,查询,算法,数组
From: https://www.cnblogs.com/filletoto/p/18032494

相关文章

  • 加密算法/常见编码
    MD51.MD5算法是单向散列算法的一种。单向散列算法也称为HASH算法,是一种将任意长度的信息压缩至某一固定长度(称之为消息摘要)的函数(该压缩过程不可逆)。在MD5算法中,这个摘要是指将任意数据映射成一个128位长的摘要信息(32位的数字字母混合码)。MD5值是32位或者16位由数字"0-9"和字......
  • 2024牛客寒假算法基础集训营6 G 人生的起落 题解
    Question2024牛客寒假算法基础集训营6G人生的起落定义一个三元组\((x,y,z)\)是“v-三元组”当且仅当该三元组满足以下条件:\(x=z\)\(x>y\)现在需要你构造一个\(n\)个正整数组成的数组,所有元素之和恰好等于\(S\),且恰好有\(k\)个长度威\(3\)的连续子数组......
  • 算法面经
    数组88. 合并两个有序数组经典逆向双指针voidmerge(vector<int>&nums1,intm,vector<int>&nums2,intn){for(inti=m-1,j=n-1,k=m+n-1;~j;k--){nums1[k]=i>=0&&nums1[i]>nums2[j]?nums1[i--]:......
  • POJ--3468 A Simple Problem with Integers(线段树/树状数组)
    记录11:032024-2-25http://poj.org/problem?id=1961线段树树状数组把区间增加转变为单点增加,利用两个树状数组\(c_0和c_1\)将”Clrd"转化为在树状数组\(c_0\)中,把位置l上的数加d在树状数组\(c_0\)中,把位置r+1上的数减d在树状数组\(c_1\)中,把位置l上的数......
  • 走进Kaggle的未知领域:性别和年龄推断算法解析
    ​1、环境设置:此环节将加载实现笔记本无缝功能的基本模块,包括NumPy、Pandas和TensorFlow等库。此外,它还建立了关键的环境常数,如图像尺寸和学习率,这对后续分析和模型训练至关重要。#Generalimportosimportkerasimportnumpyasnpimportpandasaspdimporttensorflow......
  • Big-Yellow的算法工程师进阶之路
    Big-Yellow的算法工程师进阶之路一、基础算法二、基础数据结构2.1链表三、......
  • 代码随想录算法训练营第二天| 977.有序数组的平方
    第一题题解首先写了一个初步解,后续再想优化思路classSolution:defsortedSquares(self,nums:List[int])->List[int]:#sortbytheabsofvalueabs_min=10000abs_min_index=0foriinrange(len(nums)):if......
  • 【深度学习】Logistic回归算法和向量化编程。全md文档笔记(代码文档已分享)
    本系列文章md笔记(已分享)主要讨论深度学习相关知识。可以让大家熟练掌握机器学习基础,如分类、回归(含代码),熟练掌握numpy,pandas,sklearn等框架使用。在算法上,掌握神经网络的数学原理,手动实现简单的神经网络结构,在应用上熟练掌握TensorFlow框架使用,掌握神经网络图像相关案例。具体......
  • 代码随想录算法训练营第二十七天| 93.复原IP地址 78.子集 90.子集II
    复原IP地址 题目链接:93.复原IP地址-力扣(LeetCode)思路:投降。在判断字符串是否合法这部分遇到了困难。classSolution{private:vector<string>result;//记录结果//startIndex:搜索的起始位置,pointNum:添加逗点的数量voidbacktracking(string&s,int......
  • 图像识别算法--VGG16
    前言:人类科技就是不断烧开水(发电)、丢石头(航天等)。深度学习就是一个不断解方程的过程(参数量格外大的方程)本文内容:1、介绍VGG16基本原理2、VGG16pytorch复现图像识别算法--VGG16目录图像识别算法--VGG161、参考文献2、VGG16理论2.1VGG16优点2.2VGG16网络结构图2.2.1复现代......