One: The basic concept of segment tree
1: Overview
segment tree, similar to Interval tree, is a complete binary tree, which holds a segment (a sub-array of arrays) in each node, and is mainly used to efficiently solve the dynamic query problem of continuous interval, because of the characteristics of the binary structure, basic ability to maintain the complexity of each operation is O (log n)
Properties: Suppose a node corresponding to the interval is [a, b], set c= (a+b)/2, the left subtree corresponding to the interval is [a,c], the right subtree corresponding to the interval is [C+1,b], the segment tree space complexity of O (n);
2: Maintenance point and Point-modified segment tree
(1) construct segment tree
function: Build (int begin,int end,int node)//Construct a segment tree Owo
Minimum value for each node in the maintenance interval
The main idea is recursive construction, if the current node record interval has only one value, then directly assigned value, otherwise recursively constructs the left and right subtree, and finally assigns the left and right to the current node
intArray[max_n];intsegtree[4*max_n+Ten];voidBuildintNodeintBeginintend) { if(Begin = =end) Segtree[node]= Array[begin];/*only one element, the node records the cell*/ Else { /*recursive construction of left and right sub-trees*/Build (2*node, Begin, (begin+end)/2); Build (2*node+1, (Begin+end)/2+1, end); /*Gets the segment information of the current node node when backtracking*/ if(segtree[2* Node] <= segtree[2* node +1]) Segtree[node]= segtree[2*node]; ElseSegtree[node]= segtree[2* node +1]; } }
View Code
(2) query minimum value
Function: query (int begin,int end,int node,int left,int right)//queries [Begin,end] The minimum value, the next 3 parameters are used in recursion for convenience of calculation. Fill in the 0,0,n when calling;
such as: I want to query [600,6000] The minimum value, just use Query (600,6000,0,0,n);
The main idea is to divide the interval [a, b] of the query into nodes on the segment tree, and then combine the intervals represented by these nodes to get the required information
intQuery (intBeginintEndintNodeintLeftintRight//minimum value for query [Begin,end]{ intLEFTQ, RIGHTQ; //if it does not intersect at all, it returns a sufficiently large number of INF, which is recommended for Int_max if(Left > End | | Right < BEGIN)returnINF; /*If you fully include*/ /*returns the value of the current node*/ if(Begin >= left && end <=Right )returnSegtree[node]; /*Compare the minimum value of the right subtree of Saozi*/LEFTQ= Query (begin, (begin+end)/2,2*node,left,right); RIGHTQ= Query ((begin+end)/2+1, End,2*node+1, Left,right); /*return this value*/ returnmin (LEFTQ,RIGHTQ); }
View Code
(3) Single node update
function:void updata (int begin, int end,int node, int IND, int Add)//Add the node representing the [begin,end] interval numbered nodes Plus
voidUpdata (intBeginintEndintNodeintIndintAdd/*Single-node update*/ { //if it is currently a leaf node, it is updated directly if(begin==end) {Segtree[node]+=add; return; } intM= (left+right) >>1;//' >>1 ' is equivalent to dividing by 2 if(ind<=m) Updata (left,m,node*2, Ind,add);//Two-point search ElseUpdata (m+1, right,node*2+1, Ind,add);//same Two-point search /*Update parent Node*/Segtree[node]=min (segtree[node*2],segtree[node*2+1]); }
View Code
3. Segment tree for maintenance intervals and interval modifications
(1) Overview
Given an array of n elements a1,a2,...,an, your task is to design a data structure that supports the following two operations.
Add (l,r,v). Increase the value of the Al,al+1,...,ar by V.
Query (L,R): Calculates the element and, minimum, and maximum values of a subsequence al,al+1,...,ar.
(2) construct segment tree
function: void maintain (int o,int l,int R)//Construction of a node o, corresponding to [l,r] interval
intMinv[max_n],maxv[max_n],sumv[max_n],addv[max_n]; voidMaintain (intOintLintR) { intlc=o*2, rc=o*2+1;//left dial hand tree Ovo and right sub-tree Owo if(r>L) {Sumv[o]=SUMV[LC]+SUMV[RC];//consider the left and right sub-treesminv[o]=min (MINV[LC],MINV[RC]); Maxv[o]=Max (MAXV[LC],MAXV[RC]); } Minv[o]+=addv[o];//Consider the add Operationmaxv[o]+=Addv[o]; Sumv[o]+=addv[o]* (r-l+1);}
View Code
(3) Operation 1.add
function: void update (int o,int l,int R)//add operation
Recursive access to the node all to invoke the Maintain function update
voidUpdateintOintLintR//Add Operation{ intlc=o*2, rc=o*2+1; if(yl<=l && y2>=r) addv[o]+=v;//recursive boundary, add value for cumulative boundary Else { intm=l+ (r-l)/2; if(yl<=M) Update (LC,L,M); if(y2>m) Update (rc,m+1, R); } maintain (O,L,R); //Recalculate additional information for this node before recursion ends}
View Code
(4) Operation 2. Query
function: void query (int o,int l,int r,int Add)
The query interval is decomposed into several disjoint sub-intervals, and the query results of each sub-interval are merged, but it is important to note that the result of each boundary interval cannot be used directly, but also consider the influence of ancestor nodes on it. For convenience, we add a parameter to the recursive query function that represents the sum of all ancestor node add values for the current interval
int_min,_max,_sum;//global variables, minimum, maximum, and sum of current positions andvoidQueryintOintLintRintadd) { if(Yl<=l && y2>=r)//recursive boundary: Update the answer with additional information about the boundary interval{_sum+=sumv[o]+add* (r-l+1); _min=min (_min,minv[o]+add); _ Max=max (_max,maxv[o]+add); } Else //recursive statistics, cumulative parameters Add { intm=l+ (r-l)/2; if(yl<=m) query (o*2, l,m,add+Addv[o]); if(y2>m) query (o*2+1, m+l,r,add+Addv[o]); }}
View Code
Not to be continued ...
Line tree-Continuously updated spicy