基于C#实现树状数组
有一种数据结构是神奇的,神秘的,它展现了位运算与数组结合的神奇魅力,太牛逼的,它就是树状数组,这种数据结构不是神人是发现不了的。
一、概序
假如我现在有个需求,就是要频繁的求数组的前 n 项和,并且存在着数组中某些数字的频繁修改,那么我们该如何实现这样的需求?当然大家可以往真实项目上靠一靠。
**① 传统方法:**根据索引修改为 O(1),但是求前 n 项和为 O(n)。
**② 空间换时间方法:**我开一个数组 sum[],sum[i]=a[1]+…+a[i],那么有点意思,求 n 项和为 O(1),但是修改却成了 O(N),这是因为我的 Sum[i]中牵涉的数据太多了,那么问题来了,我能不能在相应的 sum[i]中只保存某些 a[i]的值呢?好吧,下面我们看张图。

从图中我们可以看到 S[]的分布变成了一颗树,有意思吧,下面我们看看 S[i]中到底存放着哪些 a[i]的值。
S[1]=a[1];
S[2]=a[1]+a[2];
S[3]=a[3];
S[4]=a[1]+a[2]+a[3]+a[4];
S[5]=a[5];
S[6]=a[5]+a[6];
S[7]=a[7];
S[8]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8];
之所以采用这样的分布方式,是因为我们使用的是这样的一个公式:S[i]=a[i-2k+1]+…+a[i]。
其中:2k 中的 k 表示当前 S[i]在树中的层数,它的值就是 i 的二进制中末尾连续 0 的个数,2k 也就是表示 S[i]中包含了哪些 a[],举个例子: i=610=01102 ;可以发现末尾连续的 0 有一个,即 k=1,则说明 S[6]是在树中的第二层,并且 S[6]中有 21 项,随后我们求出了起始项:
a[6-21+1]=a[5],但是在编码中求出 k 的值还是有点麻烦的,所以我们采用更灵巧的 Lowbit 技术,即:2k=i&-i 。
则:S[6]=a[6-21+1]=a[6-(6&-6)+1]=a[5]+a[6]。
二、代码
1、神奇的 Lowbit 函数
#region 当前的sum数列的起始下标/// <summary>/// 当前的sum数列的起始下标/// </summary>/// <param name="i"></param>/// <returns></returns>public static int Lowbit(int i){return i & -i;}#endregion
2、求前 n 项和
比如上图中,如何求 Sum(6),很显然 Sum(6)=S4+S6,那么如何寻找 S4 呢?即找到 6 以前的所有最大子树,很显然这个求和的复杂度为 logN。
#region 求前n项和/// <summary>/// 求前n项和/// </summary>/// <param name="x"></param>/// <returns></returns>public static int Sum(int x){int ans = 0;var i = x;while (i > 0){ans += sumArray[i - 1];//当前项的最大子树i -= Lowbit(i);}return ans;}#endregion
3、修改
如上图中,如果我修改了 a[5]的值,那么包含 a[5]的 S[5],S[6],S[8]的区间值都需要同步修改,我们看到只要沿着 S[5]一直回溯到根即可,同样它的时间复杂度也为 logN。
public static void Modify(int x, int newValue){//拿出原数组的值var oldValue = arr[x];for (int i = x; i < arr.Length; i += Lowbit(i + 1)){//减去老值,换一个新值sumArray[i] = sumArray[i] - oldValue + newValue;}}
最后上总的代码:
using System;using System.Collections.Generic;using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.IO;namespace ConsoleApplication2
{public class Program{static int[] sumArray = new int[8];static int[] arr = new int[8];public static void Main(){Init();Console.WriteLine("A数组的值:{0}", string.Join(",", arr));Console.WriteLine("S数组的值:{0}", string.Join(",", sumArray));Console.WriteLine("修改A[1]的值为3");Modify(1, 3);Console.WriteLine("A数组的值:{0}", string.Join(",", arr));Console.WriteLine("S数组的值:{0}", string.Join(",", sumArray));Console.Read();}#region 初始化两个数组/// <summary>/// 初始化两个数组/// </summary>public static void Init(){for (int i = 1; i <= 8; i++){arr[i - 1] = i;//设置其实坐标:i=1开始int start = (i - Lowbit(i));var sum = 0;while (start < i){sum += arr[start];start++;}sumArray[i - 1] = sum;}}#endregionpublic static void Modify(int x, int newValue){//拿出原数组的值var oldValue = arr[x];arr[x] = newValue;for (int i = x; i < arr.Length; i += Lowbit(i + 1)){//减去老值,换一个新值sumArray[i] = sumArray[i] - oldValue + newValue;}}#region 求前n项和/// <summary>/// 求前n项和/// </summary>/// <param name="x"></param>/// <returns></returns>public static int Sum(int x){int ans = 0;var i = x;while (i > 0){ans += sumArray[i - 1];//当前项的最大子树i -= Lowbit(i);}return ans;}#endregion#region 当前的sum数列的起始下标/// <summary>/// 当前的sum数列的起始下标/// </summary>/// <param name="i"></param>/// <returns></returns>public static int Lowbit(int i){return i & -i;}#endregion}
}

相关文章:
基于C#实现树状数组
有一种数据结构是神奇的,神秘的,它展现了位运算与数组结合的神奇魅力,太牛逼的,它就是树状数组,这种数据结构不是神人是发现不了的。 一、概序 假如我现在有个需求,就是要频繁的求数组的前 n 项和&#x…...
Ubuntu Server 20.04.6下Anaconda3安装Pytorch
环境 Ubuntu 20.04.6 LTS Anaconda3-2023.09-0-Linux-x86_64.sh conda 23.7.4 Pytorch 1.11.0 安装 先创建一个工作环境,环境名叫lia: conda create -n lia python3.8环境的使用方法如下: conda activate lia # 激活环境 conda deactiv…...
C#-关于日志的功能扩展
目录 一、日志Sink(接收器) 二、Trace追踪实现日志 三、日志滚动 一、日志Sink(接收器) 安装NuGet包:Serilog Sink有很多种,这里介绍两种: Console接收器(安装Serilog.Sinks.Console); File接收器(安装…...
小程序禁止二次转发分享私密消息动态消息
第一种用法:私密消息 私密消息:运营人员分享小程序到个人或群之后,该消息只能在被分享者或被分享群内打开,不可以二次转发。 用途:主要用于不希望目标客群外的人员看到的分享信息,比如带有较高金额活动的…...
普乐蛙绵阳科博会一场VR科普航天科学盛宴科普知识
普乐蛙绵阳科普展:一场科学盛宴,点燃孩子探索欲望的火花! 普乐蛙绵阳科普展正在如火如荼地进行中,吸引了无数孩子和家长的热情参与。这场科普盛宴以独特的内外视角,让人们感受到科学的魅力,激发了孩子们对知识的渴望和…...
FFNPEG编译脚本
下面是一个ffmpeg编译脚本: #!/bin/bash set -eu -o pipefail set eu o pipefailFFMPEG_TAGn4.5-dev build_path$1 git_repo"https://github.com/FFmpeg/FFmpeg.git" cache_tool"" sysroot"" c_compiler"gcc" cxx_compile…...
Python期末复习题库(下)——“Python”
小雅兰期末加油冲冲冲!!! 1. (单选题)下列关于文件打开模式的说法,错误的是( C )。 A. r代表以只读方式打开文件 B. w代表以只写方式打开文件 C. a代表以二进制形式打开文件 D. 模式中使用时,文件可读可写 2. (单选题)下列选项中,以追加…...
tauri中使用rust调用动态链接库例子(使用libloading库和libc库)
前言 当前采用桌面端框架位tauri,现在需要调用读卡器等硬件设备,硬件厂商提供了32位的动态链接库,现在记录例子,需要注意的点是使用libloading库和libc库, [package] name "yyt-device-rust" version &q…...
Leetcode—739.每日温度【中等】
2023每日刷题(四十二) Leetcode—739.每日温度 单调栈实现思想 从右到左实现代码 class Solution { public:vector<int> dailyTemperatures(vector<int>& temperatures) {int n temperatures.size();stack<int> st;vector<i…...
毕业设计单片机可以用万能板吗?
毕业设计单片机可以用万能板吗? 可以是可以,就是焊接起来比较麻烦,特别是有好几个重复连线点的时候,检测起来就不那么容易了,而且布线看起来乱糟糟的,如果后期一不小心把线弄断了,查起来就更麻烦了&#x…...
spring boot整合Jasypt实现配置加密
文章目录 目录 文章目录 前言 一、Jasypt是什么? 二、使用步骤 1.引入 2.测试使用 3.结果 总结 前言 一、Jasypt是什么? Jasypt(Java Simplified Encryption)是一个Java库,提供了一种简单的加密解密方式,…...
java学校高校运动会报名信息管理系统springboot+jsp
课题研究方案: 结合用户的使用需求,本系统采用运用较为广泛的Java语言,springboot框架,HTML语言等关键技术,并在idea开发平台上设计与研发创业学院运动会管理系统。同时,使用MySQL数据库,设计实…...
Java(七)(Lambda表达式,正则表达式,集合(Collection,Collection的遍历方式))
目录 Lambda表达式 省略写法(要看懂) 正则表达式 语法 案例 正则表达式的搜索替换和分割内容 集合进阶 集合体系结构 Collection Collection的遍历方式 迭代器 增强for循环 Lambda表达式遍历Collection List集合 ArrayList LinkedList 哈希值 HashSet底层原理 …...
华为OD机试 - 二叉树计算(Java JS Python C)
目录 题目描述 输入描述 输出描述 用例 题目解析 JS算法源码 Java算法源码...
鸿蒙(HarmonyOS)应用开发——基础组件
组件 组件化是一种将复杂的前端应用程序分解成小的、独立的部分的方法。这些部分被称为组件,它们可以重复使用,可以与其他组件组合使用以创建更复杂的组件,并且它们有自己的生命周期和状态。 组件化的目的是提高开发效率和代码重用率&#…...
Vue3的项目创建到启动
Vue3的项目创建 检查node版本创建 npm init vuelatest 安装依赖 项目启动 启动成功...
开关电源基础而又硬核的知识
1.什么是Power Supply? Power Supply是一种提供电力能源的设备,它可以将一种电力能源形式转换成另外一种电力能源形式,并能对其进行控制和调节。 根据转换的形式分类:AC/DC、DC/DC、DC/AC、AC/AC 根据转换的方法分类:线性电源、…...
LightDB23.4 支持转换sql中中文空格和逗号为英文空格和逗号
功能介绍 在Lightdb数据库兼容Oracle的语法时,发现Oracle支持sql语句中使用中文空格和中文逗号,为了方便用户迁移到Lightdb,在Lightdb23.4版本中支持了转换中文空格和逗号的功能。该功能由GUC参数lightdb_convert_chinese_char来控制开关&am…...
EM@常见平面曲线的方程的不同表示方式
文章目录 abstract常见曲线的不同形式小结:一览表分析圆锥曲线的极坐标方程非标准位置的圆锥曲线参数方程应用比较 refs abstract 常见平面曲线的方程的不同表示方式 常见曲线的不同形式 下面以平面曲线为对象讨论参数方程通常是对普通方程的补充和增强,曲线的普通方程(直角…...
element使用小结
1、tabel表头文字自定义效果(换行,不同颜色) 换行: // 方法一 <el-table-columnprop"otherCost":label"本期累计\n(元)"> // 通过:label添加\n </el-table-column>.xx .cell {white-space: pre-…...
DeepSeek-Coder-V2-Lite-Instruct用户调研:开发者眼中的AI编程助手痛点与需求
DeepSeek-Coder-V2-Lite-Instruct用户调研:开发者眼中的AI编程助手痛点与需求 【免费下载链接】DeepSeek-Coder-V2-Lite-Instruct 开源代码智能利器——DeepSeek-Coder-V2,性能比肩GPT4-Turbo,全面支持338种编程语言,128K超长上下…...
Qwen3-TTS-12Hz-1.7B-Base应用场景:智能音箱多语种交互语音引擎升级
Qwen3-TTS-12Hz-1.7B-Base应用场景:智能音箱多语种交互语音引擎升级 重要提示:本文仅讨论技术实现方案,所有内容均基于公开技术文档和测试数据,不涉及任何政治敏感内容,完全符合内容安全规范。 1. 智能音箱语音交互的现…...
Bambu Studio 3D打印切片实战指南:从技术原理到场景应用
Bambu Studio 3D打印切片实战指南:从技术原理到场景应用 【免费下载链接】BambuStudio PC Software for BambuLab and other 3D printers 项目地址: https://gitcode.com/GitHub_Trending/ba/BambuStudio Bambu Studio作为一款专为3D打印优化的开源切片软件&…...
Notepad--:国产跨平台文本编辑器的终极指南与快速上手
Notepad--:国产跨平台文本编辑器的终极指南与快速上手 【免费下载链接】notepad-- 一个支持windows/linux/mac的文本编辑器,目标是做中国人自己的编辑器,来自中国。 项目地址: https://gitcode.com/GitHub_Trending/no/notepad-- Note…...
「码动四季·开源同行」go语言:统一认证与授权如何保障服务安全
认证与授权对于当前的互联网应用是非常重要的基础功能:认证用于验证当前用户的身份,而授权意味着用户在认证成功后,会被系统授予访问系统资源的权限。只有具备相应身份和权限的人才能访问系统中的相应资源,比如在购物网站中你只能…...
RIFE帧插值技术:视频增强领域的智能插帧解决方案
RIFE帧插值技术:视频增强领域的智能插帧解决方案 【免费下载链接】video2x A machine learning-based video super resolution and frame interpolation framework. Est. Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/vi/video2x …...
MTK平台录音杂音怎么来的?从AudioALSACaptureDataClientAurisysNormal的mDropPopSize说起
MTK平台录音杂音问题深度解析:从硬件初始化到算法优化的全链路解决方案 在移动设备音频开发领域,MTK平台的录音杂音问题一直是困扰开发者的典型痛点。特别是录音起始阶段出现的"爆破音"或"电流声",不仅影响用户体验&…...
GLM-OCR在跨境电商中的应用:多语言商品说明书OCR→自动翻译预处理
GLM-OCR在跨境电商中的应用:多语言商品说明书OCR→自动翻译预处理 1. 项目概述与背景 跨境电商卖家经常面临一个共同难题:来自不同国家的商品说明书语言各异,手动翻译不仅耗时耗力,还容易出错。传统OCR工具虽然能识别文字&#…...
Mermaid Live Editor:用代码绘制专业图表的终极免费工具
Mermaid Live Editor:用代码绘制专业图表的终极免费工具 【免费下载链接】mermaid-live-editor Edit, preview and share mermaid charts/diagrams. New implementation of the live editor. 项目地址: https://gitcode.com/GitHub_Trending/me/mermaid-live-edit…...
5大核心功能深度解析:Umi-OCR开源离线文字识别工具的技术实现与应用指南
5大核心功能深度解析:Umi-OCR开源离线文字识别工具的技术实现与应用指南 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二…...
