Leetcode上一道题,给定一个整数数组,要实现:

  • 求[i, j]所有元素的和,0 <= i <= j <= n - 1,sumRange(i, j)
  • 数组的元素会被修改, update(i, val)
  • 这两个函数会被均匀的调用很多次

最简单的方法是求和O(n),修改元素O(1),时间复杂度太大,使用Segment Tree可以将二者的时间复杂度均变为O(logn)

Segment Tree:

  • 叶子节点是输入数组中的所有元素
  • 内部节点是其孩子节点所带信息的merge
  • Segment Tree可以由数组实现,数组索引i的左孩子为$2 * i + 1$,右孩子为$2 * i + 2$,父节点在$\lceil (i - 1) / 2 \rceil$
  • Segment Tree的高度为$\lceil log_2n \rceil$, 因此该数组的大小为$2 * 2 ^{\lceil log_2n\rceil} - 1$

一下代码是上述题目的C++递归实现:

 1 #include <math.h>
 2 #include <vector>
 3 #include <iostream>
 4 using namespace std;
 5
 6 class segTree{
 7 public:
 8     vector<int> tree;
 9     int n;
10     segTree(vector<int>& arr){
11         n = arr.size();
12         int treeSize = 2 * pow(2, ceil(log2(double(n)))) - 1;
13         tree.resize(treeSize);
14         buildSegTree(arr, 0, 0, n - 1);
15     }
16
17
18     void buildSegTree(vector<int>& arr, int treeIndex, int lo, int hi){
19         if(lo == hi){
20             tree[treeIndex] = arr[lo];
21             return;
22         }
23         int mid = lo + (hi - lo) / 2;
24         buildSegTree(arr, 2 * treeIndex + 1, lo, mid);
25         buildSegTree(arr, 2 * treeIndex + 2, mid + 1, hi);
26         tree[treeIndex] = merge(tree[2 * treeIndex + 1], tree[2 * treeIndex + 2]);
27     }
28
29
30     int querySegTree(int treeIndex, int lo, int hi, int i, int j){
31         if(lo > j || hi < i)
32             return 0;
33         if(i <= lo && j >= hi)
34             return tree[treeIndex];
35
36         int mid = lo + (hi - lo) / 2;
37
38         if(i > mid)
39             return querySegTree(2 * treeIndex + 2, mid + 1, hi, i, j);
40         else if(j <= mid)
41             return querySegTree(2 * treeIndex + 1, lo, mid, i, j);
42
43         int leftQuery = querySegTree(2 * treeIndex + 1, lo, mid, i, mid);
44         int rightQuery = querySegTree(2 * treeIndex + 2, mid + 1, hi, mid + 1, j);
45
46         return merge(leftQuery, rightQuery);
47     }
48
49
50     void updateValSegTree(int treeIndex, int lo, int hi, int arrIndex, int val){
51         if(lo == hi){
52             tree[treeIndex] = val;
53             return;
54         }
55
56         int mid = lo + (hi - lo) / 2;
57
58         if(arrIndex > mid)
59             updateValSegTree(2 * treeIndex + 2, mid + 1, hi, arrIndex, val);
60         else if(arrIndex <= mid)
61             updateValSegTree(2 * treeIndex + 1, lo, mid, arrIndex, val);
62
63         tree[treeIndex] = merge(tree[2 * treeIndex + 1] , tree[2 * treeIndex + 2]);
64     }
65
66
67     int merge(int& v1, int& v2){
68         return v1 + v2;
69     }
70 };
71
72
73 int main(){
74     vector<int> arr1 = {1, 3, 5, 7, 9, 11};
75     segTree test(arr1);
76     for(int item : test.tree)
77         cout << item << " ";
78     cout << endl;
79     int sum = test.querySegTree(0, 0, test.n - 1, 0, 2);
80     cout << "sum = " << sum << endl;
81     test.updateValSegTree(0, 0, test.n - 1, 1, 4);
82     int updatedSum  = test.querySegTree(0, 0, test.n - 1, 0, 2);
83     cout << "updated sum = " << updatedSum << endl;
84     return 0;
85 }

转载于:https://www.cnblogs.com/betaa/p/11416493.html

Segment Tree相关推荐

  1. C++Persistent segment tree持久段树的实现算法(附完整源码)

    C++Persistent segment tree持久段树的实现算法 C++Persistent segment tree持久段树的实现算法完整源码(定义,实现,main函数测试) C++Persi ...

  2. C语言实现段树segment tree(附完整源码)

    C语言实现段树segment tree 段树结构体定义 实现以下6个接口 完整实现和main测试源码 段树结构体定义 typedef struct segment_tree {void *root; ...

  3. 【线段树】Segment Tree

    Segment Tree 时间限制: 1 Sec  内存限制: 512 MB 提交: 107  解决: 23 [提交] [状态] [命题人:admin] 题目描述 Mcginn opens the c ...

  4. HDURevenge of Segment Tree(第二长的递增子序列)

    HDURevenge of Segment Tree(第二长的递增子序列) 题目链接 题目大意:这题是求第二长的递增子序列. 解题思路:用n^2的算法来求LIS,可是这里还要记录一下最长的那个序列是否 ...

  5. Segment Tree Beats 区间最值问题

    Segment Tree Beats 区间最值问题 线段树一类特殊技巧! 引出:CF671C Ultimate Weirdness of an Array 其实是考试题,改题的时候并不会区间取最值,区 ...

  6. poj 2892 Tunnel Warfare (Splay Tree instead of Segment Tree)

    poj.org/problem?id=2892 poj上的一道数据结构题,这题正解貌似是Segment Tree,不过我用了Splay Tree来写,而且我个人认为,这题用Splay Tree会更好写 ...

  7. HDU5086Revenge of Segment Tree(数论)

    HDU5086Revenge of Segment Tree(数论) 题目链接 题目大意:给出长度为n的数组.然后要求累计里面的每一个子串的和. 解题思路:枚举起点和终点,推断每一个数属于多少条线段. ...

  8. codeforces EDU segment tree

    本文以codeforces EDU segment tree为资料 content introdcution problems & solutions A. Sign alternation ...

  9. BZOJ.4695.最假女选手(线段树 Segment tree Beats!)

    题目链接 区间取\(\max,\ \min\)并维护区间和是普通线段树无法处理的. 对于操作二,维护区间最小值\(mn\).最小值个数\(t\).严格次小值\(se\). 当\(mn\geq x\)时 ...

最新文章

  1. 报javax.servlet.ServletException: Servlet.init() for servlet springmvc threw exception异常 的解决方案...
  2. JS-用js的for循环实现九九乘法表以及其他算数题等
  3. linux pycharm 数字键盘失效
  4. 软件工程第一周开课博客
  5. 浏览器支持java_为什么我下载了java并提示浏览器不支持j
  6. Spring事务的实现方式和实现原理
  7. 生活大爆炸soft kitty
  8. vba移动文件_你想要的爬虫、VBA系列教程这里都有!
  9. oracle 11g jdk设置,java-如何从oracle 11g jdbc 7/14 jdk 1.7中的读取调...
  10. layui的lay-verify参数验证的问题
  11. pubwin扫描安装
  12. JavaScript-网页特效
  13. 安卓 每日一题 2020年5-6月问题及答案
  14. lambada 表达式
  15. mysql 创建重复数据库_MySQL数据库,如何处理重复的数据?
  16. KPA EtherCAT主站协议栈基准
  17. 用Python实现喷墨打印机定期清洗喷头
  18. 幼儿教师需要掌握的计算机技巧,幼儿教师应掌握的五项教学技能!
  19. 全国计算机access二级真题,全国计算机二级access历年真题及答案
  20. 电脑系统重装win10的方法教程,win10系统重装教程

热门文章

  1. 2019.02.11 bzoj4818: [Sdoi2017]序列计数(矩阵快速幂优化dp)
  2. hadoop题目(一)
  3. NPOI随笔——图片在单元格等比缩放且居中显示
  4. rabbitmq 连接过程详解
  5. Something haunts me in Python
  6. qt 手动设置控件的位置
  7. Syntax error: word unexpected (expecting ))错误的解决方法
  8. s4-介质访问控制子层-1 MAC子层
  9. 序列化picklejson模块
  10. cp linux 显示进度条_Unix/Linux/Mac os下 文件互传