Poj 3264 balanced lineup [rmq evaluate range most value template question]

Source: Internet
Author: User
Balanced lineup
Time limit:5000 Ms   Memory limit:65536 K
Total submissions:26435   Accepted:12401
Case time limit:2000 ms

Description

For the daily milking, Farmer John'sNCows (1 ≤N≤ 50,000) always line up in the same order. One day farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range
Of cows from the milking lineup to play the game. However, for all the cows to have fun they shocould not differ too much in height.

Farmer John has made a listQ(1 ≤Q≤ 200,000) potential groups of cows and Their heights (1 ≤Height≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest
Cow in the group.

Input

Line 1: two space-separated integers, NAnd Q.
Lines 2 .. N+ 1: Line I+ 1 contains a single integer that is the height of cow I 
Lines N+ 2 .. N+ Q+ 1: two integers AAnd B(1 ≤ ABN), Representing the range of cows from ATo BIntrusive.

Output

Lines 1 .. Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.

Sample Input

6 31734251 54 62 2

Sample output

630

Source

Usaco 2007 January silver Question:Give you the height of N cows in a certain order, and find the difference between the highest and the lowest cows in a given range. Algorithm:Rmq calculates the maximum value of the interval. Data Source: Lrj algorithm competition getting started classic training guide p197 ~ 198 PS: The template code in the book is a little problematic. You can modify it yourself...

Rmq Analysis

(PS: The idea is described in the same document)

Rmq (range minimum/maximum query) problems:
The rmq problem is the most important problem in the given range. Of course, the simplest algorithm is O (n), but the O (n) algorithm is not efficient enough for queries with a large number of times (up to 1 million times. You can use the line segment tree to optimize the algorithm to O (logn) (the online segment tree stores the maximum value of the line segment ). However, the sparse_table algorithm is the best: it can achieve O (1) query efficiency after O (nlogn) preprocessing. The sparse table algorithm is divided into two parts: preprocessing and query (for the minimum value ).

 
Preprocessing: (take the interval minimum value as an example) O (nlogn)
Preprocessing uses the DP idea. f (I, j) represents the minimum value in the [I, I + 2 ^ J-1] interval (that is, the value starting from I, the minimum value of an element with a length of 2 ^ J ,).

We can open up an array to save f (I, j) values.
For example, F (0, 0) indicatesMinimum valueThat is, num [0], F (0, 2) indicates the minimum value between [0, 3], and F (2, 4) indicates the minimum value between [2, 17 ].
Note: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.

Recursive equation:F (I, j) = min {f (I, J-1), F (I + 2 ^ (J-1), J-1 )}

Note:2 ^ j <= n so the number of elements in the array cannot exceed nlogn, and none of them can be calculated at the constant time, so the total time is O (nlogn)

The Preprocessing code is as follows:

// Edit the element from 1 to n

void RMQ_init(){for(int i = 1; i <= n; i++){d_min[i][0] = a[i]; // 2^0 = 1}for(int j = 1; (1<<j) <= n; j++) // 2^j <= n{for(int i = 1; i+(1<<j)-1 <= n; i++) // i+2^j-1 <= n{d_min[i][j] = min(d_min[i][j-1], d_min[i+(1<<(j-1))][j-1]);}}}

Query: O (1)
Suppose we want to query the minimum value from R to L, first make K the largest integer that satisfies 2 ^ k <= R-L + 1, the two intervals starting with L and ending with R with 2 ^ K are combined to cover the query interval [L, R].

Two overlapping interval F (L, k) is [l, l + 2 ^ k-1], F (R-2 ^ k + 1, K) that is, [R-2 ^ k + 1, R ].

Because it is the minimum value, it does not matter if some elements are repeated for several times (Note: if the elements are accumulated, repeated elements are not allowed ).


We have obtained the minimum value of F (L, k) for [l, l + 2 ^ k-1], F (R-2 ^ k + 1, K) is the minimum value of [R-2 ^ k + 1, R]
We only need to 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 ))
Therefore, we must note that the J value in the pre-processing f (I, j) only needs to calculate log (n + 1)/log (2, and we only need to calculate the I value to the N-2 ^ k + 1.

The query code is as follows:

Int rmq_min (int l, int R) {int K = 0; while (1 <(k + 1) <= R-L + 1) K ++; // If 2 ^ (k + 1) <= R-L + 1, then K can also add 1 return min (d_min [l] [K], d_min [R-(1 <k) + 1] [k]);}

PS: it seems that there is another efficiency of O (N). For the moment, you cannot understand ing... just use this.

/** 3264 * accepted * 8168 K * 1719 Ms * C ++ * 00002b * O (N * logn) */# include <cstdio> # include <cmath> # include <algorithm> using namespace STD; const int maxn = 50000 + 10; int d_max [maxn] [20]; int d_min [maxn] [20]; int A [maxn]; int N, Q; void rmq_init () {for (INT I = 1; I <= N; I ++) {d_min [I] [0] = A [I]; // 2 ^ 0 = 1d_max [I] [0] = A [I];} for (Int J = 1; (1 <j) <= N; j ++) // 2 ^ j <= n {for (INT I = 1; I + (1 <j)-1 <= N; I ++) // I + 2 ^ J-1 <= n {d _ Min [I] [J] = min (d_min [I] [J-1], d_min [I + (1 <(J-1)] [J-1]); d_max [I] [J] = max (d_max [I] [J-1], d_max [I + (1 <(J-1)] [J-1]);} int rmq_min (int l, int R) {int K = 0; while (1 <(k + 1) <= R-L + 1) K ++; // If 2 ^ (k + 1) <= R-L + 1, then K can also add 1 return min (d_min [l] [K], d_min [R-(1 <k) + 1] [k]);} int rmq_max (int l, int R) {int K = 0; while (1 <(k + 1) <= R-L + 1) K ++; // If 2 ^ (k + 1) <= R-L + 1, then K can add 1 return max (d_max [l] [K], d_max [R-(1 <k) + 1] [k]);} int main () {While (scanf ("% d", & N, & Q )! = EOF) {for (INT I = 1; I <= N; I ++) {scanf ("% d", & A [I]) ;} rmq_init (); int A, B; while (Q --) {scanf ("% d", & A, & B); printf ("% d \ n", rmq_max (, b)-rmq_min (a, B) ;}} return 0 ;}

Just asked Orc. He said he used it.Line Segment treeAfter doing this, I feel that the efficiency is higher than above. I need to post the code and ideas.

/*
* My code is built first and then searched
* Find the maximum and minimum values of each interval when creating a building.
* When you find the interval, you will know the maximum and minimum values.
*/

/** Accepted * 2388 kb * 1766 Ms * C ++ * 1690 B */# include <cstdio> # include <iostream> # include <algorithm> # include <cstring> using namespace STD; # define n 50001int V [N], Max, min; struct node {int left, right; int Max, min; int mid () {return (left + right) /2;} t [N * 3]; void build (INT root, int L, int R) // build {T [root]. left = L; t [root]. right = r; // printf ("% d", t [root]. left, t [root]. right); // you can perform "single-step debugging" to see how it is created if (L = r) // if there are no children, the child tree has been created {T [root]. max = T [root]. min = V [l]; return;} else {int mid = T [root]. mid (); Build (root <1, L, mid); // the order of creation is from left to right, root <1 is equivalent to root * 2 build (root <1 | 1, Mid + 1, R ); // root <1 | 1 is equivalent to root * 2 + 1 t [root]. max = max (T [root * 2]. max, t [root * 2 + 1]. max); t [root]. min = min (T [root * 2]. min, t [root * 2 + 1]. min) ;}} void query (INT root, int L, int R) // find the line segment {// printf ("% d", t [root]. left, t [root]. right); // you can perform one-step debugging when searching to see how it looks up if (T [root]. left = L & T [root]. right = r) {max = max (T [root]. max, Max); min = min (T [root]. min, min); return;} else {int mid = T [root]. mid (); If (r <= mid) // find {query (root <1, L, r) in the left child;} else if (L> mid) // find {query (root <1 | 1, L, R);} else // split two halves {query (root <1, l, mid); query (root <1 | 1, Mid + 1, R) ;}} int main () {int I, j, n, m; scanf ("% d", & N, & M); for (I = 1; I <= N; I ++) scanf ("% d ", & V [I]); Build (1, 1, n); for (I = 1; I <= m; I ++) {int St, en; scanf ("% d", & St, & en); max =-1000111222; min = 1000111222; query (1, St, en ); printf ("% d \ n", max-min);} return 0 ;}



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.