Stock Prediction
Difficulty: Hard

George is very concerned about the stock options his company has granted him, because the company's stock price has fluctuated unpredictably and has often failed to meet expectations.  With this in mind, George has decided to sell his options.  Before doing so, he would like to perform a series of calculations.

Stock price history is presented as an array of positive integers, $A = \{a_0, a_1, \ldots, a_{n-1}\}$, which represents the average price per day of that stock. For a given day $d\ (0 \le d < n)$ and margin $M$, George needs to find the longest subarray containing the day's entry as a minimum,  $a_d$, and all other entries not exceeding $a_d+M$.

That is, he has to find the longest subarray, $A[l, r] = \{a_l, a_{l+1}, \ldots, a_r\}$, such that 

- $0 \le l \le d \le r < n$
- $a_d = minimum\{A[l, r]\}$
- $ \forall i \in [l, r], a_d \le a_i \le a_d + M$

George asks you to help him solve this problem.

Input Format:
The first list contains an integer $n$ which represents the length of the array $A$. The second line contains $n$ space-separated integers, $a_0, a_1, \ldots, a_{n-1}$, which represent the element of array $A$. The next line contains the number of queries $Q$. Each of the subsequent $Q$ lines contain two integers $d$ and $M$ which represent the index of the element, which should be minimal and be included in subarray, and margin, respectively.  

Output Format:
For each query output the length of the longest subarray with the required properties.

**Constraints**  
$1 \le n \le 5\cdot 10^4$  
$1 \le A[i] \le 10^9, 0 \le i < n$  
$1 \le Q \le 10^5$  
$0 \le d < n$  
$0 \le M \le 10^9$

Sample Input:
    5
    3 5 2 6 1
    2
    0 2
    2 3

Sample Output:
    2
    3

Python 3 starter code:


Reference solution (Python):
    /**
     * Created by Bo You on 2014/12/2.
     */
    object Solution {

      class Node(val l: Int, val r: Int, val minValue: Int, val maxValue: Int)

      def build(a: Array[Int], n: Int, sz: Int, ng: Int): Array[Node] = {
        def iter(cur: Int, ans: List[Node]): List[Node] = {
          if (cur == ng) {
            return ans
          } else {
            val l = sz * cur
            val r = Math.min(n, l + sz)
            val x = (l to r - 1).foldLeft(Integer.MAX_VALUE)((cur, idx) => Math.min(cur, a(idx)))
            val y = (l to r - 1).foldLeft(Integer.MIN_VALUE)((cur, idx) => Math.max(cur, a(idx)))
            return iter(cur + 1, ans.+:(new Node(l, r, x, y)))
          }
        }
        return iter(0, List[Node]()).reverse.toArray
      }

      def work(q: Array[Int], a: Array[Int], segs: Array[Node]): Int = {
        def iter(cur: Int, d: Int, acc: Int): Int = {
          if (cur < 0 || cur >= segs.length) {
            return acc
          } else if (segs(cur).minValue >= a(q(0)) && segs(cur).maxValue <= a(q(0)) + q(1)) {
            return iter(cur + d, d, acc + segs(cur).r - segs(cur).l)
          } else {
            val fi = if (d == 1) segs(cur).l else segs(cur).r - 1
            var ret = acc
            var i = fi
            while (true) {
              if (a(i) < a(q(0)) || a(i) > a(q(0)) + q(1)) {
                return ret
              }
              ret += 1
              i += d
            }
            return -1
          }
        }
        var idx = -1
        for (i <- 0 to segs.length - 1) {
          if (segs(i).l <= q(0) && segs(i).r > q(0)) {
            idx = i
          }
        }
        val lp = (segs(idx).l to q(0) - 1).reverse.takeWhile(i => a(i) >= a(q(0)) && a(i) <= a(q(0)) + q(1))
        var rp = (q(0) + 1 to segs(idx).r - 1).takeWhile(i => a(i) >= a(q(0)) && a(i) <= a(q(0)) + q(1))
        return 1 + lp.length + rp.length +
          (if (lp.length == q(0) - segs(idx).l) iter(idx - 1, -1, 0) else 0) +
          (if (rp.length == segs(idx).r - q(0) - 1) iter(idx + 1, 1, 0) else 0)
      }

      def main(args: Array[String]): Unit = {
        val n = readLine().toInt
        val a = readLine().split(" ").map(_.toInt).toArray
        val sz = Math.sqrt(n).toInt
        val ng = if (n % sz != 0) n / sz + 1 else n / sz
        val segs = build(a, n, sz, ng)
        val numQueries = readLine().toInt
        for (i <- 1 to numQueries) {
          val q = readLine().split(" ").map(_.toInt)
          println(work(q, a, segs))
        }
      }

    }