树的结构 数据结构
What is a segment tree?
什么是段树?
A segment tree is a full binary tree where each node represents an interval. A node may store one or more data members of an interval which can be queried later.
段树是完整的二叉树,其中每个节点代表一个间隔。 节点可以存储一个或多个间隔的数据成员,以后可以查询该成员。
Why do we need Segment tree?
为什么我们需要细分树?
Many problems require that we give results based on query over a range or segment of available data. This can be the tedious and slow process, especially if the number of queries is large.
许多问题要求我们根据对可用数据范围或数据段的查询得出结果。 这可能是一个繁琐而缓慢的过程,尤其是在查询数量很大的情况下。
A segment tree lets us process such queries efficiently in logarithmic order of time.
段树使我们能够以对数时间顺序有效地处理此类查询。
How do we make a Segment tree?
我们如何制作细分树?
Let the data be in array arr[]
让数据位于数组arr []中
The root of our tree will represent the entire interval of data we are interested in, i.e, arr[0...n-1].
树的根将代表我们感兴趣的整个数据间隔,即arr [0 ... n-1] 。
Each leaf of the tree will represent a range consisting of just a single element. Thus the leaves represent arr[0], arr[1], arr[2] ... arr[n-1].
树的每片叶子将代表一个仅包含一个元素的范围。 因此,叶子代表arr [0] , arr [1] , arr [2] ... arr [n-1] 。
The internal nodes will represent the merged result of their child nodes.
内部节点将代表其子节点的合并结果。
Each of the children nodes could represent approximately half of the range represented by their parent.
每个子节点可代表其父节点所代表范围的大约一半。
Segment Tree generally contains three types of method: Build, Query, and Update.
细分树通常包含三种类型的方法:生成,查询和更新。
Let’s take an example:
让我们举个例子:
Problem: Range minimum query
问题:范围最小查询
You are given N numbers and Q queries. There are two types of queries.
系统会为您提供N个数字和Q个查询。 有两种类型的查询。
Find the minimum number in range [l,r].
在[l,r]范围内找到最小值。
Update the element at ith position of array to val.
将数组第 i 个位置的元素更新为val 。
Basic Approach:
基本方法:
We can find minimum element in O(N) and update the element in O(1). But if N or Q (query) is a very large number, it will be very slow.
我们可以在O(N)中找到最小元素,并在O(1)中更新元素。 但是,如果N或Q(查询)是一个非常大的数字,它将非常慢。
But it can be solved in logarithmic time with segment trees.
但这可以用段树在对数时间内解决。
The root of the tree is at index 1
树的根在索引1处
The children then will be at 2*i and 2*i+1 index.
然后,子级将位于2 * i和2 * i + 1索引处。
#include<iostream>
using namespace std;
int tree[400005]; // segment tree structure
int arr[100005]; // input tree
//Build
void build_tree(int node, int a, int b){
//node represent the current node number
// a,b represent the current node range
//for leaf a == b
if(a==b){
//for single element minimum will be the element itself
tree[node] = arr[a];
return;
}
int mid = (a + b) >> 1; // middle element
tree[node] =
build_tree(node*2,a,mid)+ // call for left half
build_tree(node*2+1,mid+1,b);//call for right half
}
//Query
int query_tree(int node, int a, int b, int i, int j){
//i, j represents the range to be queried
if(a > b || a > j || b < i){ return INT_MAX;} // out of range
if(a>= i && b<=j){
return tree[node]; //segment within range
}
int mid = a+ b >> 1;
int q1 = query_tree(node*2,a,mid,i,j); //left child query
int q2 = query_tree(node*2+1,mid+1,b,i,j); // right child query
return q1>q2?q2:q1;
}
void update_tree(int node, int a,int b, int i, int val){
if(a>b||a>i||b<i){
return;//Out of range
}
if(a==b){
tree[node] = val;
return;
}
int mid = (a+b) >> 1;
tree[node] = update_tree(node*2,a,mid,i,val) + // updating left child
update_tree(node*2+1,mid+1,b,val); //updating right child
}
翻译自: https://www.includehelp.com/data-structure-tutorial/segment-trees.aspx
树的结构 数据结构