307区域和检索 - 数组可修改(线段树)

2023-10-04 21:10

本文主要是介绍307区域和检索 - 数组可修改(线段树),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、题目描述

给定一个整数数组  nums,求出数组从索引 i 到 j  (i ≤ j) 范围内元素的总和,包含 i,  j 两点。

update(i, val) 函数可以通过将下标为 i 的数值更新为 val,从而对数列进行修改。

说明:

  • 数组仅可以在 update 函数下进行修改。
  • 你可以假设 update 函数与 sumRange 函数的调用次数是均匀分布的。

2、示例

Given nums = [1, 3, 5]sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8

3、题解

基本思想:线段树

  • 建立线段树:将nums值放入tree最后面作为叶子节点,然后不断更新父节点等于子节点值之和tree[i]=tree[2*i]+tree[2*i+1]
  • 更新线段树:将叶子节点及其往上的节点直到根节点都要更新,时间复杂度O(logn)
  • 查找检索线段树:如果左边界是右子节点,将该节点加入到sum否则往上查找其父节点值,如果右边界是左子节点,将该节点加入到sum否则往上查找其父节点值,这样不断往上查找直到左右边界相遇,时间复杂度O(logn)
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
class NumArray {
public:NumArray(vector<int>& nums) {if(nums.size()==0)  return;sum.resize(nums.size());sum[0]=nums[0];for(int i=1;i<nums.size();i++)sum[i]=sum[i-1]+nums[i];}void update(int i, int val) {int diffval=i==0?val-sum[i]:val-(sum[i]-sum[i-1]);if(diffval==0)  return;for(int j=i;j<sum.size();j++)sum[j]+=diffval;}int sumRange(int i, int j) {return i==0?sum[j]:sum[j]-sum[i-1];}
private:vector<int> sum;
};
class NumArray1 {
public:NumArray1(vector<int>& nums) {//建立线段树:将nums值放入tree最后面作为叶子节点,然后不断更新父节点等于子节点值之和tree[i]=tree[2*i]+tree[2*i+1]if(nums.size()==0)  return;n=nums.size();tree.resize(2*n);for(int i=0,j=n;i<nums.size();i++,j++)tree[j]=nums[i];for(int i=n-1;i>0;i--)tree[i]=tree[2*i]+tree[2*i+1];}void update(int i, int val) {//更新线段树:将叶子节点及其往上的节点直到根节点都要更新,时间复杂度O(logn)int pos=i+n;int diffval=val-tree[pos];if(diffval==0)  return;while(pos>0){tree[pos]+=diffval;pos/=2;}}int sumRange(int i, int j) {//查找检索线段树:如果左边界是右子节点,将该节点加入到sum否则往上查找其父节点值,//如果右边界是左子节点,将该节点加入到sum否则往上查找其父节点值,这样不断往上查找直到左右边界相遇,时间复杂度O(logn)int sum=0;i+=n;j+=n;while(i<=j){//如果左边界是右子节点,将该节点加入到sum这样避免误加左子节点值if(i%2==1){sum+=tree[i];i++;}//如果右边界是左子节点,将该节点加入到sum这样避免误加右子节点值if(j%2==0){sum+=tree[j];j--;}//之后就更新边界到其父节点通过加其父节点值就加了两个子节点值,这样时间复杂度只有O(logn)i/=2;j/=2;}return sum;}
private:vector<int> tree;int n;
};
int main()
{vector<int> nums={1,3,5};NumArray1* obj = new NumArray1(nums);cout<<obj->sumRange(0,2)<<endl;obj->update(1,2);cout<<obj->sumRange(0,2)<<endl;return 0;
}

 

这篇关于307区域和检索 - 数组可修改(线段树)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/2729

相关文章

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

python修改字符串值的三种方法

《python修改字符串值的三种方法》本文主要介绍了python修改字符串值的三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录第一种方法:第二种方法:第三种方法:在python中,字符串对象是不可变类型,所以我们没办法直接

Mysql8.0修改配置文件my.ini的坑及解决

《Mysql8.0修改配置文件my.ini的坑及解决》使用记事本直接编辑my.ini文件保存后,可能会导致MySQL无法启动,因为MySQL会以ANSI编码读取该文件,解决方法是使用Notepad++... 目录Myhttp://www.chinasem.cnsql8.0修改配置文件my.ini的坑出现的问题

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :