首页 > 其他分享 >树状数组

树状数组

时间:2023-04-02 14:00:58浏览次数:49  
标签:树状 int res 数组 lowbit query

树状数组

简单记录一下模板和用法,不做深入证明探究!

能解决的问题:

  • 区间查询前缀和
  • 单点修改(某个值+一个数)

是一个在 logN复杂度就能完成以上操作的数据结构。严格来说,能解决的问题是线段树的子集。

树状数组能够解决的问题,线段树一定可以解决!但是树状数组代码简单好写,相比臃肿庞大的线段树,能用树状数组优雅的解决问题,想必也是让人神往的吧!

看个图例:

 

 

不难看出,树状数组是分层(高度)的。对于下标i在多少层,只需要将其转换成二进制,并看一下它后面有几个0就好了,若有k个0,则在2^k层

例如: (4)10 = (100)2 ,其二进制下有两个零,所以在2^2 = 4 层。

三个函数:

lowbit()

这个函数主要用来求一个数的二进制下尾数有k个0,并返回2^k。

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

add()

void add(int x,int v){
    //在 x 位置 加上 v
    for(int i=x;i<=n;i+=lowbit(i)) tr+= v; 
}

如果不是添加,而是想替换呢?

只需要将参数V  改成 v-x即可!

query()

int query(int x){
    int res = 0;
    for(int i=x;i>0;i-=lowbit(i)) res+=tr[i];
    return res;
}

对于区间[x,y]的前缀和,我们只需要 query(y)-query(x-1) 即可!(这里用到了差分的思想)

 

初始化:

将tr数组开在全局变量,即初始化为0。对于每个输入的数,只需要调用add函数即可。

 

板子题:

这里有一个板子

 

 代码如下:

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 100010;
int n,m;

int a[N],tr[N];
int lowbit(int x){
    return x& -x;
}
void add(int x,int v){
    //在 x 位置 加上 v
    for(int i=x;i<=n;i+=lowbit(i)) tr[i]+= v; 
}
int query(int x){
    int res = 0;
    for(int i=x;i>0;i-=lowbit(i)) res+=tr[i];
    return res;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) add(i,a[i]);
    
    while( m --){
        int k,x,y;
        scanf("%d%d%d",&k,&x,&y);
        if(k==0){
            printf("%d\n",query(y)-query(x-1));
        }
        else{
            add(x,y);
        }
    } 
    
} 

 

标签:树状,int,res,数组,lowbit,query
From: https://www.cnblogs.com/Uninstalllingyi/p/17280370.html

相关文章

  • Go 语言数组和切片的区别
    原文链接:Go语言数组和切片的区别在Go语言中,数组和切片看起来很像,但其实它们又有很多的不同之处,这篇文章就来说说它们到底有哪些不同。另外,这个问题在面试中也经常会被问到,属于入门级题目,看过文章之后,相信你会有一个很好的答案。数组数组是同一种数据类型元素的集合,数组在......
  • 453.最小操作次数使数组元素相等
    最小操作次数使数组元素相等给你一个长度为n的整数数组,每次操作将会使n-1个元素增加1。返回让数组所有元素相等的最小操作次数。示例1:输入:nums=[1,2,3]输出:3解释:只需要3次操作(注意每次操作会增加两个元素的值):[1,2,3]=>[2,3,3]=>[3,4,3]=>[4,4,4]......
  • 1438. 绝对差不超过限制的最长连续子数组
    力扣题目链接给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。如果不存在满足条件的子数组,则返回 0 。 示例1:输入:nums=[8,2,4,7],limit=4输出:2解释:所有子数组......
  • [LeetCode] 1338. Reduce Array Size to The Half 数组大小减半
    Youaregivenanintegerarray arr.Youcanchooseasetofintegersandremovealltheoccurrencesoftheseintegersinthearray.Return theminimumsizeofthesetsothat atleast halfoftheintegersofthearrayareremoved.Example1:Input:arr=......
  • java方法-稀疏数组
    稀疏数组当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组稀疏数组的处理方式是:记录数组一共有几行几列,有多少个不同值把具体不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模如图:左原始数组,右稀疏数组 ......
  • 树状数组
    树状数组简介树状数组是一种用于维护\(n\)个数的区间和的数据结构。一般能用树状数组做的题,都可以使用线段树来做。相较于码量,树状数组的码量要比线段树少许多,不过相对应的,它所能实现的功能没有线段树多。好的,不多说废话,下面进入正题。例题1:P3374【模板】树状数组1例题......
  • 剑指offer42(Java)-连续子数组的最大和(简单)
    题目:输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。示例1:输入:nums=[-2,1,-3,4,-1,2,1,-5,4]输出:6解释: 连续子数组 [4,-1,2,1]的和最大,为 6。提示:1<= arr.length<=10^5-100<=arr[i]<=1......
  • HJ69_矩阵乘法_数组
    思路:三层循环实现矩阵相乘。importsysa=[]forlineinsys.stdin:  a.append(list(map(int,line.strip().split())))#print(a)matrix1=a[3:3+a[0][0]]matrix2=a[3+a[0][0]:]nw=[[0foriinrange(a[2][0])]foriinrange(a[0][0])]forminrange(a[0][0]): ......
  • VBA 对象数组排序算法分享
     FunctionSrotObjectByProperty(objsToSortAsVariant,PropertyNameAsString,Optional降序AsBoolean=True)IfIsEmpty(objsToSort)ThenExitFunctionIfInStr(TypeName(objsToSort),"()")<1ThenExitFunction'IsArray()issom......
  • Java 数组
    数组数组是相同类型数据的有序集合数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们数组的声明和创建首先必须声明数组变量,才能在程序中使用数组。Java语言使用new操作符来创建数组,语......