【算法】树状数组

前言

众所周知,通过前缀和,我们可以很快的在一个很大的数组中求出区间和,但是如果想要去修改数组中的一个数的值,前缀和就无法实现。所以来学习一个新的数据结构:树状数组
(文章中关于树状数组的截图来自于b站视频BV1ce411u7qP)

树状数组

当我们想求出一个数组中起始位置和下标i之间的所有元素和,需要从头开始遍历到下标i。但是这样的效率特别低,所以就有如下思考:把相邻数字两两求和后存在一个新数组中,这样遍历的时候会节省一半的时间,但是在求和的时候仍然要遍历很多的数据,效率仍然很低。不如多加几层,直到新开的数组中只有一个元素为止。这样即使要求和的数字很多,也只需要利用这些额外的数组来计算出需要的答案。如下图所示,从下到上,第一层是原始数组,第二层是原始数组中每相邻两个数合成后得到的数组,第三层是原始数组中每相邻四个数合成后得到的数组。如果要计算出前15个数字,那么只需要计算4个数,大大加快计算速度。
但是会发现,在这些数中,有一些数字是用不到的,如果去掉这些数字后,保留下来的有用的数字恰好和原始数组的长度相同。
请看下图:
图片源自网络
将这个树形结构中的数从左到右放进一个新的数组中,这个数组就是树状数组。每一个元素的下标就是合成这个数的数中,在原始数组中最右侧的那个数的下标。假设下标是从1开始的。我们已知树状数组中的一个数的下标,要怎么得知这个数是由原数组中多少个数合成的呢?
lowbit函数就能实现
代码如下

def lowbit(x):
    return x&(-x)

这个函数很简单,只有一条语句,通过这样的计算可以很高效的求出一个数在二进制下,最右边的1的权是多少。
通过观察发现,树状数组中的下标为i的元素恰好是由原始数据中连续的lowbit(i)个数合成的。而放在树中,同一层元素的lowbit()都是相同的,他上一层元素的lowbit()恰好是这层的两倍。
直到这个规律之后我们就能做以下的操作了

计算前m个元素的和

我们知道了所求区间最右侧lowbit(m)个元素之和存在树状数组下标m的位置,还剩下长度为m-lowbit(m)的区间,也一样可以在树状数组中找出他最右侧的lowbit(m-lowbit(m))个元素和,没错,只要通过递归或循环就能计算出结果了

增减下标i的元素的值

访问下标i的位置,然后对其进行增减操作,这步操作后,会影响到树状数组中在其上层的元素,所以需要接着不断加上lowbit(i)然后找到他上层的元素进行修改。树状数组的初始化其实就是开辟一个空的数组,自定义一个add()函数可以对下标i的元素进行增加,然后从前往后遍历不断的执行add()函数即可。

例题P3374 【模板】树状数组 1

在这里插入图片描述

代码实现

python

def lowbit(x):
    return x&(-x)
def add(x, n, k):#x为树状数组的编号,n为数组大小,k为要加的值
    while x<=n:
        f[x]+=k
        x+=lowbit(x)
def ask(x):
    if x==0:
        return 0
    return ask(x-lowbit(x))+f[x]
# 循环版本
# def ask(x):
#     res=0
#     while x>0:
#         res+=f[x]
#         x-=lowbit(x)
#     return res
n,m=map(int, input().split())
a=list(map(int, input().split()))
f=[0]*(n+1)
for i in range(1,n+1):
    add(i, n, a[i-1])
while m>0:
    op,x,y=map(int, input().split())
    if op==1:
        add(x, n, y)
    else:
        print(ask(y)-ask(x-1))
    m-=1

c++

#include<bits/stdc++.h>
using namespace std;
int n,m,tree[2000010];
int lowbit(int k)
{
    return k & -k;
}
void add(int x,int k)
{
    while(x<=n)
    {
        tree[x]+=k;
        x+=lowbit(x);
    }
}
int sum(int x)
{
    int ans=0;
    while(x!=0)
    {
        ans+=tree[x];
        x-=lowbit(x);
    }
    return ans;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int a;
        scanf("%d",&a);
        add(i,a);
    }
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        if(a==1)
            add(b,c);
        if(a==2)
            cout<<sum(c)-sum(b-1)<<endl;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/916592.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java项目实战II基于微信小程序的私家车位共享系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在城市化进…

ZeroSSL HTTPS SSL证书ACMESSL申请3个月证书

目录 一、引言 二、准备工作 三、申请 SSL 证书 四、证书选型 五、ssl重要性 一、引言 目前免费 Lets Encrypt、ZeroSSL、BuyPass、Google Public CA SSL 证书&#xff0c;一般免费3-6个月。从申请难易程度分析&#xff0c;zerossl申请相对快速和简单&#xff0c;亲测速度非…

pipx安装提示找不到包

执行&#xff1a; pipx install --include-deps --force "ansible6.*"WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by NewConnectionError(<pip._vendor.urllib3.connection.HTTPSConnection …

react + ts定义接口类型写法

接口&#xff08;未进行ts定义&#xff09; export async function UserList(params: {// keyword?: string;current?: number;pageSize?: number;},// options?: { [key: string]: any }, ) {return request<API1.UserList>(http://geek.itheima.net/v1_0/mp/artic…

Golang超详细入门教程

Golang超详细入门教程 部分图片可能加载不出来&#xff0c;所以这里我上传到了自己的个人网站上也可以查看&#xff1a;http://dahua.bloggo.chat/testimonials/490.html 一、数据类型转换 C语言中数据可以隐式转换或显示转换, 但是Go语言中数据只能显示转换格式: 数据类型(…

Cannot resolve org.apache.tomcat.embed:tomcat-embed-core:9.0.60标红解决办法

解决方法是&#xff1a; MyBatis 会扫描这个包下的所有接口&#xff0c;并将这些接口注册为 MyBatis 的 Mapper。 把这个加上后&#xff0c;问题解决&#xff01;

游戏引擎学习第九天

视频参考:https://www.bilibili.com/video/BV1ouUPYAErK/ 修改之前的方波数据&#xff0c;改播放正弦波 下面主要讲关于浮点数 1. char&#xff08;字符类型&#xff09; 大小&#xff1a;1 字节&#xff08;8 位&#xff09;表示方式&#xff1a;char 存储的是一个字符的 A…

C#设计模式(12)——享元模式(Flyweight Pattern)

前言 享元模式通过共享对象来减少内存使用和提高性能。 代码 public abstract class Flyweight {public abstract void Control(); }public class ComputerFlyweight : Flyweight {private string _operator;public ComputerFlyweight(string name){_operator name;}public o…

upload-labs通关练习

目录 环境搭建 第一关 第二关 第三关 第四关 第五关 第六关 第七关 第八关 第九关 第十关 第十一关 第十二关 第十三关 第十四关 第十五关 第十六关 第十七关 第十八关 第十九关 第二十关 总结 环境搭建 upload-labs是一个使用php语言编写的&#xff0c…

【云原生系列--Longhorn的部署】

Longhorn部署手册 1.部署longhorn longhorn架构图&#xff1a; 1.1部署环境要求 kubernetes版本要大于v1.21 每个节点都必须装open-iscsi &#xff0c;Longhorn依赖于 iscsiadm主机为 Kubernetes 提供持久卷。 apt-get install -y open-iscsiRWX 支持要求每个节点都安装 N…

Elastic Agent:可灵活地在任何地方发送和处理任何数据

作者&#xff1a;来自 Elastic Nima Rezainia Elastic Agent 是一款功能强大且用途广泛的工具&#xff0c;可用于从各种数据源&#xff08;包括自定义用户应用程序&#xff09;收集日志和指标。现在&#xff0c;Elastic Agent 提供了无与伦比的灵活性&#xff0c;可以将数据准确…

一、HTML

一、基础概念 1、浏览器相关知识 这五个浏览器市场份额都非常大&#xff0c;且都有自己的内核。 什么是内核&#xff1a; 内核是浏览器的核心&#xff0c;用于处理浏览器所得到的各种资源。 例如&#xff0c;服务器发送图片、视频、音频的资源&#xff0c;浏览…

IDEA旗舰版编辑器器快速⼊门(笔记)

简介&#xff1a;javaweb开发必备软件之IDEA期间版介绍 DEA编辑器器版本介绍 官⽹网&#xff1a;https://www.jetbrains.com/地址&#xff1a;https://www.jetbrains.com/idea/download/#sectionmac DEA 分社区版(Community) 和 旗舰版(Ultimate)&#xff0c;我们做JavaWeb开…

【鸿蒙开发】第十五章 H5与端侧交互、Cookies以及Web调试

目录 1. H5与端侧交互 1.1 应用侧调用前端页面函数 1.2 前端页面调用应用侧函数 1.2.1 复杂类型使用方法 1.3 建立应用侧与前端页面数据通道 2 管理页面跳转及浏览记录导航 2.1 历史记录导航 2.2 页面跳转 2.3 跨应用跳转 3 管理Cookie及数据存储 3.1 Cookie管理 3…

【优选算法】双指针

目录 一、[移动零](https://leetcode.cn/problems/move-zeroes/description/)二、[复写零](https://leetcode.cn/problems/duplicate-zeros/description/)三、[快乐数](https://leetcode.cn/problems/happy-number/)四、 [盛最多水的容器](https://leetcode.cn/problems/contai…

C++常用的特性-->day05

友元的拓展语法 声明一个类为另外一个类的友元时&#xff0c;不再需要使用class关键字&#xff0c;并且还可以使用类的别名&#xff08;使用 typedef 或者 using 定义&#xff09;。 #include <iostream> using namespace std;// 类声明 class Tom; // 定义别名 using …

Vue3 + Vite 构建组件库的整体流程

Vue3 Vite 构建组件库的流程 本文教你如何用 Vue Vite&#xff0c;一步一步构建一个组件库并发布到 npm 的整体流程 1. 通过 vite 命令创建一个基本的项目结构&#xff08;这里选用 vue ts 的项目&#xff09; npm create vitelatest2. 在项目中创建一个 lib 目录&#xf…

Ubuntu22.04.2 k8s部署

k8s介绍 简单介绍 通俗易懂的解释&#xff1a; Kubernetes&#xff08;也被称为 K8s&#xff09;就像是一个大管家&#xff0c;帮你管理你的云计算服务。想象一下&#xff0c;你有很多个小程序&#xff08;我们称之为“容器”&#xff09;&#xff0c;每个都在做不同的事情&…

UniApp的Vue3版本中H5配置代理的最佳方法

UniApp的Vue3版本中H5项目在本地开发时需要配置跨域请求调试 最开始在 manifest.json中配置 总是报404&#xff0c;无法通过代理请求远程的接口并返回404错误。 经过验证在项目根目录创建 vite.config.js文件 vite.config.js内容: // vite.config.js import {defineConfig }…

Android OpenGL ES详解——实例化

目录 一、实例化 1、背景 2、概念 实例化、实例数量 gl_InstanceID 应用举例 二、实例化数组 1、概念 2、应用举例 三、应用举例——小行星带 1、不使用实例化 2、使用实例化 四、总结 一、实例化 1、背景 假如你有一个有许多模型的场景&#xff0c;而这些模型的…