1.“树状数组”数据结构的一种应用

  对含有n个元素的数组(a[1],...,a[k],...,a[n]):

  (1)求出第i个到第j个元素的和,sum=a[i]+...+a[j]。

    进行j-i+1次加法,复杂度为O(j-i+1)

  (2)任意修改其中某个元素的值。

    使用数组下标可以直接定位修改,时间复杂度为O(1)

  对于同时支持上述两种操作的系统中,求和操作(1)求任意连续个数组元素和的平均时间复杂度为O(n),修改操作(2)时间复杂度是O(1)。如果系统中大量进行上述两种操作m次,其中执行操作(1)概率1/p,操作(2)概率1-1/p,则系统时间复杂度为:

  可以使用树状数组使得上述两种操作的时间复杂度为O(m*logn)

2.树状数组介绍

  核心思想:

    (1)树状数组中的每个元素是原数组中一个或者多个连续元素的和。

    (2)在进行连续求和操作a[1]+...+a[n]时,只需要将树状数组中某几个元素的和即可。时间复杂度为O(lgn)

    (3)在进行修改某个元素a[i]时,只需要修改树状数组中某几个元素的和即可。时间复杂度为O(lgn)

  下图就是一个树状数组的示意图:

  解释如下:

  1) a[]: 保存原始数据的数组。(操作(1)求其中连续多个数的和,操作(2)任意修改其中一个元素)

    e[]: 树状数组,其中的任意一个元素e[i]可能是一个或者多个a数组中元素的和。如e[2]=a[1]+a[2]; e[3]=a[3]; e[4]=a[1]+a[2]+a[3]+a[4]。

  2) e[i]是几个a数组中的元素的和?

    如果数字 i 的二进制表示中末尾有k个连续的0,则e[i]是a数组中2^k个元素的和,则e[i]=a[i-2^k+1]+a[i-2^k+2]+...+a[i-1]+a[i]。

    如:4=100(2)  e[4]=a[1]+a[2]+a[3]+a[4];

      6=110(2)  e[6]=a[5]+a[6]

      7=111(2)  e[7]=a[7]

  3) 后继:可以理解为节点的父亲节点。是离它最近的,且编号末位连续0比它多的就是它的父亲,如e[2]是e[1]的后继;e[4]是e[2]的后继。

      如e[4] = e[2]+e[3]+a[4] = a[1]+a[2]+a[3]+a[4] ,e[2]、e[3]的后继就是e[4]。

      后继主要是用来计算e数组,将当前已经计算出的e[i]添加到他们后继中。

    前驱:节点前驱的编号即为比自己小的,最近的,最末连续0比自己多的节点。如e[7]的前驱是e[6],e[6]的前驱是e[4]。

       前驱主要是在计算连续和时,避免重复添加元素。

      如:Sum(7)=a[1]+...+a[7]=e[7]+e[6]+e[4]。(e[7]的前驱是e[6], e[6]的前驱是e[4])

    计算前驱与后继:

      lowbit(i) = ( (i-1) ^ i) & i ;

      节点e[i]的前驱为 e[ i - lowbit(i) ];

      节点e[i]的前驱为 e[ i + lowbit(i) ]

3.树状数组代码示例

 1 #include <iostream>
 2 #include <stdio.h>
 3
 4 using namespace std;
 5
 6 int input(int*,int*,int);    ///输入数据
 7 int calStageSum(int*,int);    ///计算树状数组
 8 int getSum(int*,int);    ///求出前n个数字的和
 9 int updataElement(int*,int*,int,int,int);    ///更新某一位置上的元素
10
11 int main (){
12     int n;
13     int newValue;
14     cout<<"Input the n(n>3) :";
15     cin>>n;
16
17     int *num = new int[n+1];
18     int *sum = new int[n+1];
19
20     cout<<"Input "<<n<<" numbers"<<endl;
21     input(num,sum,n);
22     calStageSum(sum,n);
23
24     cout<<"The sum of first three number:"<<getSum(sum,3)<<endl;
25
26     cout<<"Update the 2nd number value:";
27     cin>>newValue;
28     updataElement(sum,num,n,2,newValue);
29
30     cout<<"The sum of first three number:"<<getSum(sum,3)<<endl;
31
32     delete []num;
33     delete []sum;
34     return 0;
35 }
36
37 int input(int* num,int *sum,int n){
38     for(int i=1;i<=n;i++){
39         cin>>num[i];
40         sum[i] = num[i];
41     }
42     return 0;
43 }
44
45 int calStageSum(int *sum,int n){
46     int lowbit;
47     int par;
48     for(int i=1;i<=n;i++){
49         lowbit = ((i-1)^i)&i;
50         par = lowbit+i;   ///后继节点id
51         if(par <= n){
52             sum[par] = sum[par] + sum[i];
53         }
54     }
55     return 0;
56 }
57
58 int getSum(int* sum,int n){
59     int sumPreN = 0;
60     int lowbit  = 0;
61     while(n!=0){
62         sumPreN += sum[n];
63         lowbit = ((n-1)^n)&n;
64         n = n - lowbit; ///前驱节点id
65     }
66     return sumPreN;
67 }
68
69 int updataElement(int* sum,int *num,int n,int pos,int newvalue){
70     int lowbit = 0;
71     int dis = newvalue - num[pos];
72     num[pos] = newvalue;
73     sum[pos] = sum[pos]+dis;
74
75     while(true){
76         lowbit = ((pos-1)^pos)&pos;
77         pos = pos + lowbit; ///后继节点id
78         if(pos <= n){
79             sum[pos] = sum[pos]+dis;
80         }
81         else
82             break;
83     }
84     return 0;
85 }

View Code

转载于:https://www.cnblogs.com/xudong-bupt/p/3484080.html

树状数组(Binary Indexed Tree) 总结相关推荐

  1. 树状数组 Binary Indexed Tree (B.I.T)

    树状数组 算法训练营 树状数组 (Binary Indexed Tree(B.I.T), Fenwick Tree) 是一个查询和修改复杂度都为 log(n) 的数据结构. 「前缀和查询」与「单点更新 ...

  2. 树状数组 Binary Indexed Tree/Fenwick Tree

    2018-03-25 17:29:29 树状数组是一个比较小众的数据结构,主要应用领域是快速的对mutable array进行区间求和. 对于一般的一维情况下的区间和问题,一般有以下两种解法: 1)D ...

  3. python 树状数组_树状数组(Binary Indexed Tree) 总结

    1."树状数组"数据结构的一种应用 对含有n个元素的数组(a[1],...,a[k],...,a[n]): (1)求出第i个到第j个元素的和,sum=a[i]+...+a[j]. ...

  4. 树状数组,Fenwick Tree

    Fenwick Tree, (also known as Binary Indexed Tree,二叉索引树), is a high-performance data structure to cal ...

  5. 树链剖分 or 根号分治 + dfs序 + 树状数组 ---- CF1254 D. Tree Queries

    题目链接 题目大意: 问题转化: 很容易发现:假设修改的节点是vvv. 1.vvv的子树sonvson_vsonv​直接加上(n−size[sonv])n×d\frac{(n-size[son_v]) ...

  6. 【Luogu】P3369 【模板】普通平衡树(树状数组)

    P3369 [模板]普通平衡树(树状数组) 一.树状数组 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构. ...

  7. 『ACM-算法-数据结构』信息竞赛进阶指南--树状数组 (模板)

    写在前面: 我们是主要是讲算法模板,即实现的代码,并不讲实现的原理 什么是树状数组? 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度 ...

  8. 暑假集训总结——区间DP,堆的概念及应用,STL(vector、set、pair、map、priority_queue),hash表,树状数组,图论

    序言: 经过长达十几天的集训,确实学了不少知识点.我想如果再不总结的话,6天之后又要忘完了. 所以发一篇具有总结回忆性的博客,供大家回忆. 目录会本人自己排列的时间的先后顺序来排列,可直接食用. 目录 ...

  9. HDU 1166 敌兵布阵 树状数组小结(更新)

    树状数组(Binary Indexed Tree(BIT), Fenwick Tree) 是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有 元素之和,但是每次只能修改一 ...

最新文章

  1. 背景建模与前景检测3(Background Generation And Foreground Detection Phase 3)
  2. php 怎么查看原生方法源码_怎么看电脑内存频率?这里有3种方法可以查看,新手分享...
  3. ParaEngine 一个同事的公司的开源引擎
  4. Unity基础之:UnityAPI的学习
  5. 两种方法清除Excel保护密码
  6. java源码影视源码搭建教程_新版千月影视app源码+搭建教程
  7. kido机器人用流量吗_国脉电信200元天网卡,交1700流量无线用,拉人加入还会有不错的收益,你信吗?反正我是不信!...
  8. Helgrind:螺纹错误检测器
  9. 清理localstorage_清除浏览器localstorage的数据
  10. GunPG使用教程(含密钥生成删除以及文件加密解密签名)
  11. 2021年5月程序员平均工资14926元!干5天拿了11天工资...
  12. 三星手机双微信设置方法,三星手机如何双开微信
  13. 你有必要不沾计算机一段时间英语,2014新人教版八年级英语下册第一单元必背词组及句子...
  14. 冬奥、亚运会、世界杯,顶级运动员与头部品牌们的营销盛宴
  15. shell脚本的错误检测总结
  16. 关于MAC安装windows【支持老版本】 支持安装全系列windows
  17. Windows计算器切换模式
  18. 【后端框架】MyBatis(1)
  19. 什么是单例模式 (Singleten)
  20. 浅析微信系列之漂流瓶

热门文章

  1. Spring.Net+NHibenate+Asp.Net mvc +ExtJs 系列 6 ----asp.net MVC+Extjs
  2. [SQL]死锁处理语句
  3. shell脚本判断进程是否运行
  4. 安卓音乐播放器开发实例
  5. onethink不能安装到已经存在的数据库中的问题
  6. print python excel分隔_合并/拆分 Excel?Python、VBA轻松自动化
  7. 边缘计算 — 商业模式
  8. Oracle 用户概念与基本操作
  9. 记一次JVM Metaspace溢出排查
  10. 在瑞士最大银行驱动创新