Given a sequence with a length of n, the elements in the sequence are not the same. We need to find a pair of (I, j), I <j, arr [k]> = I & arr [k] <= j, All (I <k <j ). then calculate the maximum j-I difference.
Solution: RMQ + 2. Some people are violent. It is estimated that it is a data problem. Initialize rmq first. The dp array here stores the subscript of the sequence. Then enumerate each end point x, and use rmq to query the Point j, which is the farthest from the point x, so that max [j, x-1] <x, here we need to use two points, the maximum value of the query interval is rmq. After finding the farthest vertex j, we need to find the subscript I with the smallest value in the [j, x-1] interval, and then x-I is the longest sequence that matches the condition at the end of x.
Why is it possible to divide it into two parts? Why is the longest sequence ending with x finding the point farthest from x and finding the minimum value in the interval?
First answer the first question, because we are looking for a X-1 before a j makes max [j, x-1] <x, to find the most value of the range, if the maximum value of a range is less than x, then the maximum value of its subinterval is less than x, which is obvious. If a location is found to be correct, it can ensure that all the locations above this location are consistent, and you can naturally search for the location above this location.
Now I want to answer the second question. I have found the leftmost position j. Now I want to find the one with the smallest value, the values in x are equal to I and smaller to x. If it is not the smallest one, the smallest one will jump out and yell: You are not small enough, naturally it is not a legal situation.
Test data:
4
5 4 3 6
4
6 5 4 3
C producer code:
[Cpp]
# Include <stdio. h>
# Include <string. h>
# Include <math. h>
# Deprecision MAX 51000
Int n, m, ans, arr [MAX];
Struct RMQ {
Int mmin [MAX] [20];
Int mmax [MAX] [20];
Void Create ();
Int Query (int l, int r, int kind );
} Rmq;
Inline int min (int x, int y ){
Return arr [x] <arr [y]? X: y;
}
Inline int max (int x, int y ){
Return arr [x]> arr [y]? X: y;
}
Void RMQ: Create (){
Int I, j = 2, k = 0;
For (I = 1; I <= n; ++ I)
Mmin [I] [0] = mmax [I] [0] = I;
While (j <= n) k ++, j * = 2; // use this instead of log to get 1000 ms faster
For (j = 1; j <= k; ++ j)
For (I = 1; I + (1 <j)-1 <= n; ++ I ){
Mmin [I] [j] = min (mmin [I] [j-1], mmin [I + (1 <(j-1)] [j-1]);
Mmax [I] [j] = max (mmax [I] [j-1], mmax [I + (1 <(j-1)] [j-1]);
}
}
Int RMQ: Query (int l, int r, int kind ){
Int I = r-l + 1, j = 2, k = 0;
While (j <= I) k ++, j * = 2; // use this instead of log to get 1000 ms faster
If (kind = 0)
Return min (mmin [l] [k], mmin [r-(1 <k) + 1] [k]);
Else
Return max (mmax [l] [k], mmax [r-(1 <k) + 1] [k]);
}
Int Find (int x ){
Int low = 1, high = x-1;
Int I, mid, k =-1;
While (low <= high ){
Mid = low + (high-low)/2;
I = rmq. Query (mid, x-1, 1); // Query the largest subscript of the mid to the X-1
If (arr [I]> arr [x]) low = mid + 1;
Else k = mid, high = mid-1;
}
If (k =-1) return x + 1;
I = rmq. Query (k, x-1, 0); // If repeated values are allowed, here we should look for the smallest subscript.
Return I;
}
Int main ()
{
Int I, j, k;
While (scanf ("% d", & n )! = EOF ){
For (I = 1; I <= n; ++ I)
Scanf ("% d", & arr [I]);
Rmq. Create ();
For (ans =-1, I = n; I> = 1; -- I ){
K = I-Find (I );
If (k> ans) ans = k;
}
Printf ("% d \ n", ans );
}
}
Author: woshi250hua