RMQ problem: For a sequence of length n, find the direct value of [i,j].
St algorithm: A method of dynamic programming.
Pre-processing of DP arrays
For the maximum value of the interval [i,i+2^j-1], you only need to know the maximum of the interval [i,i+2^ (j-1)-1] and the interval [i+2^ (j-1), i+2^j-1].
The recursive equation is: dp[i,i+2^j-1] = max (dp[i,i+2^ (j-1) -1],dp[i+2^ (j-1), i+2^j-1])
But for a relatively long sequence, 2^j is a very large number, and we can also see that there is no need to directly record the left and right endpoints.
The optimization for I records a starting point, J records something similar to distance, Dp[i,j] indicates the interval [i,i+2^j-1].
Optimized recursive equation: dp[i,j] = max (dp[i,j-1],dp[i+2^ (j-1), j-1])
The time complexity of preprocessing DP array is O (Nlogn).
Second, the maximum value of the query
So we start to find a range when the DP array, and then query.
But when querying, you know two endpoint l,r.
For the interval [l,r], how to query the DP array again?
The front said I represents the beginning, J represents something similar to the distance.
It is clear that L is the I. But 2^j-1 can not be r, this time will find a middle "j".
Make len = r-l+1, then 2^k <= Len (note here is not 2^k-1, disprove: when 2^k-1 = = len, l + 2^k-1 = l + len = r + 1 > R)
that [L,r] = max (dp[l,k],dp[r-(2^k) +1,k])
Query time complexity is O (1).
Although the code is relatively concise and powerful, the speed is relatively fast, but there is no line tree so many functions.
1#include <cstdio>2#include <cmath>3#include <iostream>4 using namespacestd;5 Const intMAXN =100005;6 intma[maxn][ -];7 intmi[maxn][ -];8 intA[MAXN];9 voidInitintN) {Ten for(inti =1; I <= N; ++i) Onema[i][0] = mi[i][0] =A[i]; A for(intj =1; (1<<J) <= N; ++j) - for(inti =1; i+ (1<<J)-1<= N; ++i) { -MA[I][J] = max (ma[i][j-1], ma[i+ (1<< (J-1))][j-1]); theMi[i][j] = min (mi[i][j-1], mi[i+ (1<< (J-1))][j-1]); - } - } - intRmq_max (intLintRintk) { + returnMax (Ma[l][k], ma[r-(1<< (k)) +1][k]); - } + intRmq_min (intLintRintk) { A returnMin (Mi[l][k], mi[r-(1<< (k)) +1][k]); at } - intRmqintLintR) { - intK =0; - while(1<< (k +1) <= r-l+1) -++K; - //int k = (int) (log (1.0* (r-l+1))/log (2.0));//can also be directly calculated K in //after the k is calculated, the call function is evaluated in the specific case. For example, return the maximum difference value. - returnRmq_max (l,r,k)-rmq_min (l,r,k); to } + intMain () { - intn,q; thescanf"%d%d", &n,&q);//n number, q query times * for(inti =1; I <= N; ++i)//Enter n number $scanf"%d", A +i);Panax NotoginsengInit (n);intL,r; - while(q--) {//make a Q-time query thescanf"%d%d",&l,&R); +printf"%d\n", RMQ (l,r)); A } the return 0; +}
St Algorithm
St Algorithm of RMQ problem