线段树 2016.4.13
来源:互联网 发布:行知实践园简介 编辑:程序博客网 时间:2024/05/16 10:27
一、定义
线段树(Segment Tree )是一种二叉搜索树
不是真正的完全二叉树,但十分近似
它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点
对于线段树中的每一个非叶子节点[a, b],它的左儿子表示的区间为[a, (a+b)/2],右儿子表示的区间为[(a+b)/2+1 ,b]
因此线段树是平衡二叉树
由于二叉树结构的特性,它基本能保持每个操作的时间复杂度为O(logN)
线段树在数组存储的方式下需要占用的空间约为4N
二、创建线段树
如果当前结点记录的区间只有一个值,则直接赋值
否则递归构造左右子树
回溯的时候给当前结点赋值
#include <iostream>#include <cstdio>#include <cstring>using namespace std;struct SegTree { int left, right; int val;};const int maxn = 5 + 5;int num[maxn];SegTree Tree[maxn * 4];void Build(int low, int high, int index);int main(){ for (int i=1; i<=5; ++i) { num[i] = i; } Build(1, 5, 1); for (int i=1; i<=9; ++i) { printf("%d %d %d\n", Tree[i].left, Tree[i].right, Tree[i].val); } return 0;}void Build(int low, int high, int index){ Tree[index].left = low; Tree[index].right = high; if (low == high) { Tree[index].val = num[low]; return; } else { int mid = low + (high-low)/2; Build(low, mid, index*2); Build(mid+1, high, index*2+1); }}
#include <iostream>#include <cstdio>#include <cstring>using namespace std;struct SegTree { int left, right; int Max;};const int maxn = 5 + 5;int num[maxn];SegTree Tree[maxn * 4];void Build(int low, int high, int index);int main(){ for (int i=1; i<=5; ++i) { num[i] = i; } Build(1, 5, 1); for (int i=1; i<=9; ++i) { printf("%d %d %d\n", Tree[i].left, Tree[i].right, Tree[i].Max); } return 0;}void Build(int low, int high, int index){ Tree[index].left = low; Tree[index].right = high; if (low == high) { Tree[index].Max = num[low]; return; } else { int mid = low + (high-low)/2; Build(low, mid, index*2); Build(mid+1, high, index*2+1); Tree[index].Max = max(Tree[index*2].Max, Tree[index*2+1].Max); }}
#include <iostream>#include <cstdio>#include <cstring>using namespace std;struct SegTree { int left, right; int sum;};const int maxn = 5 + 5;int num[maxn];SegTree Tree[maxn * 4];void Build(int low, int high, int index);int main(){ for (int i=1; i<=5; ++i) { num[i] = i; } Build(1, 5, 1); for (int i=1; i<=9; ++i) { printf("%d %d %d\n", Tree[i].left, Tree[i].right, Tree[i].sum); } return 0;}void Build(int low, int high, int index){ Tree[index].left = low; Tree[index].right = high; if (low == high) { Tree[index].sum = num[low]; return; } else { int mid = low + (high-low)/2; Build(low, mid, index*2); Build(mid+1, high, index*2+1); Tree[index].sum = Tree[index*2].sum + Tree[index*2+1].sum; }}
三、单结点更新 + 区间查询
#include <iostream>#include <cstdio>#include <cstring>using namespace std;struct SegTree { int left, right; int sum;};const int maxn = 5 + 5;int num[maxn];SegTree Tree[maxn * 4];void Build(int low, int high, int index);void Update(int target, int add, int index);int Query(int low, int high, int index);int main(){ for (int i=1; i<=5; ++i) { num[i] = i; } Build(1, 5, 1); Update(2, 2, 1); printf("%d\n", Query(1, 4, 1)); printf("%d\n", Query(4, 5, 1)); for (int i=1; i<=9; ++i) { printf("%d %d %d\n", Tree[i].left, Tree[i].right, Tree[i].sum); } return 0;}void Build(int low, int high, int index){ Tree[index].left = low; Tree[index].right = high; if (low == high) { Tree[index].sum = num[low]; return; } else { int mid = low + (high-low)/2; Build(low, mid, index*2); Build(mid+1, high, index*2+1); Tree[index].sum = Tree[index*2].sum + Tree[index*2+1].sum; }}void Update(int target, int add, int index){ if (Tree[index].left == Tree[index].right && Tree[index].left == target) { Tree[index].sum += add; return; } else { int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2; if (target <= mid) { Update(target, add, index*2); } else { Update(target, add, index*2+1); } Tree[index].sum = Tree[index*2].sum + Tree[index*2+1].sum; }}int Query(int low, int high, int index){ if (Tree[index].left == low && Tree[index].right == high) { return Tree[index].sum; } else { int mid = Tree[index].left + (Tree[index].right-Tree[index].left)/2; if (high <= mid) { return Query(low, high, index*2); } else if (low > mid) { return Query(low, high, index*2+1); } else { return Query(low, mid, index*2) + Query(mid+1, high, index*2+1); } }}
void Update(int target, int add, int index);Update(2, 2, 1);Query(1, 4, 1) = 12;Query(4, 5, 1) = 9;
#include <iostream>#include <cstdio>#include <cstring>using namespace std;struct SegTree { int left, right; int Max;};const int maxn = 5 + 5;int num[maxn];SegTree Tree[maxn * 4];void Build(int low, int high, int index);void Update(int target, int val, int index);int Query(int low, int high, int index);int main(){ for (int i=1; i<=5; ++i) { num[i] = i; } Build(1, 5, 1); Update(3, 6, 1); printf("%d\n", Query(2, 5, 1)); printf("%d\n", Query(3, 4, 1)); for (int i=1; i<=9; ++i) { printf("%d %d %d\n", Tree[i].left, Tree[i].right, Tree[i].Max); } return 0;}void Build(int low, int high, int index){ Tree[index].left = low; Tree[index].right = high; if (low == high) { Tree[index].Max = num[low]; return; } else { int mid = low + (high-low)/2; Build(low, mid, index*2); Build(mid+1, high, index*2+1); Tree[index].Max = max(Tree[index*2].Max, Tree[index*2+1].Max); }}void Update(int target, int val, int index){ if (Tree[index].left == Tree[index].right && Tree[index].left == target) { Tree[index].Max = val; return; } else { int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2; if (target <= mid) { Update(target, val, index*2); } else { Update(target, val, index*2+1); } Tree[index].Max = max(Tree[index*2].Max, Tree[index*2+1].Max); }}int Query(int low, int high, int index){ if (Tree[index].left == low && Tree[index].right == high) { return Tree[index].Max; } else { int mid = Tree[index].left + (Tree[index].right-Tree[index].left)/2; if (high <= mid) { return Query(low, high, index*2); } else if (low > mid) { return Query(low, high, index*2+1); } else { return max(Query(low, mid, index*2), Query(mid+1, high, index*2+1)); } }}
void Update(int target, int val, int index);Update(3, 6, 1);Query(2, 5, 1) = 6;Query(3, 4, 1) = 6;
四、区间更新 + 区间查询
#include <iostream>#include <cstdio>#include <cstring>using namespace std;struct SegTree { int left, right; int val;};const int maxn = 5 + 5;SegTree Tree[maxn * 4];void Build(int low, int high, int index);void Update(int low, int high, int val, int index);int Query(int low, int high, int index);int main(){ Build(1, 5, 1);// Update(2, 3, 2, 1);// Update(4, 5, 3, 1);// printf("%d\n", Query(1, 3, 1)); Update(1, 3, 2, 1); Update(4, 4, 3, 1); printf("%d\n", Query(1, 4, 1)); printf("%d\n", Query(1, 2, 1)); for (int i=1; i<=9; ++i) { printf("%d %d %d\n", Tree[i].left, Tree[i].right, Tree[i].val); } return 0;}void Build(int low, int high, int index){ Tree[index].left = low; Tree[index].right = high; Tree[index].val = 1; if (low == high) { return; } else { int mid = low + (high-low)/2; Build(low, mid, index*2); Build(mid+1, high, index*2+1); }}void Update(int low, int high, int val, int index){ if (Tree[index].val == val || (Tree[index].left == low && Tree[index].right == high)) { Tree[index].val = val; return; } else { if (Tree[index].val != 0) { Tree[index*2].val = Tree[index].val; Tree[index*2+1].val = Tree[index].val; Tree[index].val = 0; } int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2; if (high <= mid) { Update(low, high, val, index*2); } else if (low > mid) { Update(low, high, val, index*2+1); } else { Update(low, mid, val, index*2); Update(mid+1, high, val, index*2+1); } }}int Query(int low, int high, int index){ int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2; if (Tree[index].left == low && Tree[index].right == high) { if (Tree[index].val != 0) { return Tree[index].val * (high-low+1); } else { return Query(low, mid, index*2) + Query(mid+1, high, index*2+1); } } else { if (high <= mid) { return Query(low, high, index*2); } else if (low > mid) { return Query(low, high, index*2+1); } else { return Query(low, mid, index*2) + Query(mid+1, high, index*2+1); } }}
void Update(int low, int high, int val, int index);Update(2, 3, 2, 1);Update(4, 5, 3, 1);Query(1, 3, 1) = 5;
Update(1, 3, 2, 1);Update(4, 4, 3, 1);Query(1, 4, 1) = 9;Query(1, 2, 1) = 2;
#include <iostream>#include <cstdio>#include <cstring>using namespace std;struct SegTree { int left, right; int sum; int val;};const int maxn = 5 + 5;int num[maxn];SegTree Tree[maxn * 4];void Build(int low, int high, int index);void Update(int low, int high, int add, int index);int Query(int low, int high, int index);int main(){ for (int i=1; i<=5; ++i) { num[i] = i; } Build(1, 5, 1); Update(2, 3, 2, 1); printf("%d\n", Query(2, 2, 1)); printf("%d\n", Query(3, 4, 1)); Update(4, 5, 3, 1); printf("%d\n", Query(5, 5, 1)); for (int i=1; i<=9; ++i) { printf("%d %d %d\n", Tree[i].left, Tree[i].right, Tree[i].sum); } return 0;}void Build(int low, int high, int index){ Tree[index].left = low; Tree[index].right = high; Tree[index].val = 0; if (low == high) { Tree[index].sum = num[low]; return; } else { int mid = low + (high-low)/2; Build(low, mid, index*2); Build(mid+1, high, index*2+1); Tree[index].sum = Tree[index*2].sum + Tree[index*2+1].sum; }}void Update(int low, int high, int add, int index){ if (Tree[index].left == low && Tree[index].right == high) { Tree[index].val += add; return; } else { Tree[index].sum += add * (high-low+1); int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2; if (high <= mid) { Update(low, high, add, index*2); } else if (low > mid) { Update(low, high, add, index*2+1); } else { Update(low, mid, add, index*2); Update(mid+1, high, add, index*2+1); } }}int Query(int low, int high, int index){ if (Tree[index].left == low && Tree[index].right == high) { return Tree[index].sum + (high-low + 1) * Tree[index].val; } else { Tree[index].sum += (Tree[index].right-Tree[index].left + 1) * Tree[index].val; int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2; Update(Tree[index].left, mid, Tree[index].val, index*2); Update(mid+1, Tree[index].right, Tree[index].val, index*2+1); Tree[index].val = 0; if (high <= mid) { return Query(low, high, index*2); } else if (low > mid) { return Query(low, high, index*2+1); } else { return Query(low, mid, index*2) + Query(mid+1, high, index*2+1); } }}
void Update(int low, int high, int add, int index);Update(2, 3, 2, 1);
Query(2, 2, 1) = 4;Query(3, 4, 1) = 9;
Update(4, 5, 3, 1);
Query(5, 5, 1)
Query(5, 5, 1) = 8;
1 0
- 线段树 2016.4.13
- 线段树 2016.4.15
- 线段树?线段树!
- 线段树?线段树!
- 线段_线段树
- 线段_线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- LeetCode Climbing Stairs 70
- ssprintf,sscanf两个黑科技的作用
- Java加载和解析XML文件的两种方法
- 润乾集算报表实现参数级联查询
- java 中日志文件的输出
- 线段树 2016.4.13
- Android中的Intent Filter匹配规则介绍
- 人口普查(20)
- LeetCode - 26. Remove Duplicates from Sorted Array
- java中replace()和replaceAll()区别
- 模拟内容还未加载出来的动态小图画
- 接下来系列博客的大纲
- boost 添加rpath
- 面向对象高级——接口的基本概念和对象的多态性