一、定义
线段树(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;