The simplest method to evaluate rmq is to traverse the interval and time complexity O (N). However, when there are many queries, the time efficiency is not high. You can use a line segment treeAlgorithmOptimized to O (logn) (stores line segments in the online segment tree
But the sparse_table algorithm is better. It uses the O (nlogn) Time for preprocessing and then the O (1) Time for query.
Preprocessing:
Preprocessing uses the DP idea. f (I, j) represents the minimum value in the [I, I + 2 ^ J-1] interval. We can open up an array to save f (I, j, j.
For example, F (0, 0) indicates the minimum value between [0, 0], that is, num [0], F (0, 2) indicates the minimum value between [0, 3, F (2, 4) indicates the minimum value between [2, 17 ].
Note that because f (I, j) can be exported by f (I, j-1) and F (I + 2 ^ (J-1), J-1, the recursive initial values (all f (I, 0) = I) are known.
Therefore, we can use a bottom-up algorithm to recursively give all f (I, j) values that meet the conditions.
Query:
Suppose we want to query the minimum value from m to N, then we first find a maximum K, so that K satisfies 2 ^ k <= (n-m + 1 ). so we can divide [M, N] into two (partially overlapped) ranges with a length of 2 ^ K: [M, m + 2 ^ k-1], [N-2 ^ k + 1, N]; and we have obtained the minimum value of F (M, k) for [M, m + 2 ^ k-1, F (n-2 ^ k + 1, k) is the minimum value of [N-2 ^ k + 1, N], as long as we return the smaller one, which is the answer we want, the time complexity of this algorithm is O (1.
For example, rmq (0, 11) = min (f (0, 3), F (4, 3 ))
Note: here the space complexity is O (n * n). You can use the dynamic array method and use only two columns. finding rmq in Dynamic Planning (range minimum/maximum query with the highest value) has a small problem,CodeComments in
1 # Include <stdio. h> 2 # Include < String . H> 3 # Include <math. h> 4 # Define Max (a, B) (a)> (B )? (A) (B )) 5 6 Int Map [ 100 ] [ 100 ]; 7 /* * 8 * Recursive formula for preprocessing at the time of O (nlogn) 9 * F [I, j] = max (F [I, J-1], F [I + 2 ^ (J-1), J-1]) 10 * @ Param m Refers to the array that stores values. 11 * @ Param n Array Length 12 */ 13 Void Pre_handle ( Int * M, Int N) 14 { 15 Memset (map, 0 , Sizeof (MAP )); 16 For ( Int I = 0 ; I <n; I ++ ) 17 Map [I] [ 0 ] = M [I]; 18 Int K = ( Int ) (Log (N)/log ( 2 )); 19 For ( Int I = 1 ; I <= K; I ++) /* I indicates a column and J indicates a row. The result of each column only depends on the previous column. */ 20 For ( Int J = 0 ; J + POW ( 2 , I- 1 ) <N; j ++ ) 21 /* Note that because each column limits J + POW (2, I-1) <n, except for the first column 22 * If none of the others is n-1, the last number of each row may be incorrect, 23 * Does not affect the final result. */ 24 Map [J] [I] = max (Map [J] [I- 1 ], Map [J + ( Int ) Pow ( 2 , I- 1 )] [I- 1 ]); 25 } 26 27 Int Rmq ( Int A, Int B) 28 { 29 Int K = (Int ) (Log (B-A + 1 )/Log ( 2 )); /* The Interval Length is B-A + 1. */ 30 /* Overlap between two intervals */ 31 Return Max (Map [a] [K], map [B + 1 -( Int ) Pow ( 2 , K)] [k]); 32 } 33 34 Int Main () 35 { 36 Freopen ( " In " , " R " , Stdin ); 37 Int N; 38 Int M [ 100 ]; 39 Scanf ( " % D " ,& N ); 40 For ( Int I = 0 ; I <n; I ++) 41 Scanf ( " % D " ,& M [I]); 42 Pre_handle (m, n ); 43 Printf ( " % D \ n " , Rmq ( 2 , 10 )); 44 Printf ( " % D \ n " , Rmq ( 20 , 30 )); 45 Return 0 ; 46 }