Problem:
Score : 800 points

Problem Statement

There are N positive integers A_1, A_2, ..., A_N.
Takahashi can perform the following operation on these integers any number of times:

Choose 1 \leq i \leq N and multiply the value of A_i by -2.

Notice that he multiplies it by minus two.

He would like to make A_1 \leq A_2 \leq ... \leq A_N holds.
Find the minimum number of operations required. If it is impossible, print -1.

Constraints

1 \leq N \leq 200000

1 \leq A_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
A_1 A_2 ... A_N

Output

Print the answer.

Sample Input 1

4
3 1 4 1

Sample Output 1

3

One possible solution is:

Choose i=4 and multiply the value of A_4 by -2. A_1, A_2, A_3, A_4 are now 3, 1, 4, -2.

Choose i=1 and multiply the value of A_1 by -2. A_1, A_2, A_3, A_4 are now -6, 1, 4, -2.

Choose i=4 and multiply the value of A_4 by -2. A_1, A_2, A_3, A_4 are now -6, 1, 4, 4.

Sample Input 2

5
1 2 3 4 5

Sample Output 2

0

A_1 \leq A_2 \leq ... \leq A_N holds before any operation is performed.

Sample Input 3

8
657312726 129662684 181537270 324043958 468214806 916875077 825989291 319670097

Sample Output 3

7

Solution in Scala (2.11.7) (judge verdict: Accepted)

object Main {
  def main(args: Array[String]): Unit = {
    val s = new Main()
    s.solve()
    s.out.flush()
  }
}

class Main {
  import java.io._
  import java.util.StringTokenizer

  import scala.collection.mutable
  import scala.util.Sorting
  import math.{abs, max, min}
  import mutable.{ArrayBuffer, ListBuffer}
  import scala.reflect.ClassTag

  val MOD = 1000000007
  val out = new PrintWriter(System.out)

  def solve(): Unit = {
    val N = ni()
    val A = na(N)
    val IncR = Array.ofDim[Long](N + 1)
    val IncL = Array.ofDim[Long](N + 1)

    def mkInc(a1: Int, a2: Int) = {
      def log2_ceil(big: Int, small: Int) = {
        var i = 0
        var x = small.toLong
        while (big > x) {
          x *= 4
          i += 2
        }
        i
      }

      def log2_floor(big: Int, small: Int) = {
        var i = 0
        var x = small.toLong
        while (big >= x * 4) {
          x *= 4
          i += 2
        }
        i
      }

      if (a1 < a2) -log2_floor(a2, a1)
      else if (a1 > a2) log2_ceil(a1, a2)
      else 0
    }

    REP(N - 1, 1) { i =>
      IncR(i) = mkInc(A(i - 1), A(i))
    }

    reverse(A)
    REP(N - 1, 1) { i =>
      IncL(i) = mkInc(A(i - 1), A(i))
    }
    reverse(IncL)

    /**
      * @param i 影響が緩和される数列のを大きさ
      */
    case class Barrier(i: Int, v: Long)

    def mkR = {
      val R = Array.ofDim[Long](N + 1)
      val barriers = mutable.Stack[Barrier]()

      // R(N) == 0
      REP_r(N) { i =>
        R(i) = R(i + 1)
        if (IncR(i + 1) < 0) {
          barriers.push(Barrier(N - 1 - i, IncR(i + 1)))
        }
        else if (IncR(i + 1) > 0) {
          // 影響を受けるのはiより後ろの数列、
          R(i) += calc(i, barriers)(N - 1 - _, i => IncR(i + 1))
        }
      }

      R
    }


    def mkL = {
      val L = Array.ofDim[Long](N + 1)
      val barriers = mutable.Stack[Barrier]()

      // L(N) == 0
      REP(N, 1) { i =>
        L(i) = L(i - 1) + 1 // かならず-2を掛ける
        if (IncL(i - 1) < 0) {
          barriers.push(Barrier(i - 1, IncL(i - 1)))
        }
        else if (IncL(i - 1) > 0) {
          // 影響を受けるのはiより後ろの数列、
          L(i) += calc(i, barriers)(_ - 1, i => IncL(i - 1))
        }
      }

      L
    }

    def calc(i: Int, barriers: mutable.Stack[Barrier])(current: Int => Int, incr: Int => Long) = {
      var sum = 0L
      var inc = incr(i)
      var cur = current(i)
      while(inc > 0 && barriers.nonEmpty) {
        val prev = barriers.pop()
        sum += (cur - prev.i) * inc
        cur = prev.i
        inc += prev.v
        if (inc < 0) barriers.push(Barrier(prev.i, inc)) // 消費しきれなかった分を戻す
      }
      if (inc > 0) sum += cur * inc
      sum
    }

    val R = mkR
    val L = mkL

    val ans = map(N + 1) { i => R(i) + L(i)}.min
    out.println(ans)
  }

  def reverse[@specialized A](as: Array[A]): Unit = {
    REP(as.length / 2) { i =>
      val t = as(i)
      as(i) = as(as.length - 1 - i)
      as(as.length - 1 - i) = t
    }
  }

  class InputReader(val stream: InputStream) {
    private val reader = new BufferedReader(new InputStreamReader(stream), 32768)
    private var tokenizer: StringTokenizer = _

    def next(): String = {
      while (tokenizer == null || !tokenizer.hasMoreTokens)
        tokenizer = new StringTokenizer(reader.readLine)
      tokenizer.nextToken
    }

    def nextInt(): Int = next().toInt
    def nextLong(): Long = next().toLong
    def nextChar(): Char = next().charAt(0)
  }
  val sc = new InputReader(System.in)
  def ni(): Int = sc.nextInt()
  def nl(): Long = sc.nextLong()
  def nc(): Char = sc.nextChar()
  def ns(): String = sc.next()
  def ns(n: Int): Array[Char] = ns().toCharArray
  def na(n: Int, offset: Int = 0): Array[Int] = map(n)(_ => ni() + offset)
  def na2(n: Int, offset: Int = 0): (Array[Int], Array[Int]) = {
    val A1, A2 = Array.ofDim[Int](n)
    REP(n) { i =>
      A1(i) = ni() + offset
      A2(i) = ni() + offset
    }
    (A1, A2)
  }
  def nm(n: Int, m: Int): Array[Array[Int]] = {
    val A = Array.ofDim[Int](n, m)
    REP(n) { i =>
      REP(m) { j =>
        A(i)(j) = ni()
      }
    }
    A
  }
  def nal(n: Int): Array[Long] = map(n)(_ => nl())
  def nm_c(n: Int, m: Int): Array[Array[Char]] = map(n) (_ => ns(m))
  def REP(n: Int, offset: Int = 0)(f: Int => Unit): Unit = {
    var i = offset
    val N = n + offset
    while(i < N) { f(i); i += 1 }
  }
  def REP_r(n: Int, offset: Int = 0)(f: Int => Unit): Unit = {
    var i = n - 1 + offset
    while(i >= offset) { f(i); i -= 1 }
  }

  def map[@specialized A: ClassTag](n: Int, offset: Int = 0)(f: Int => A): Array[A] = {
    val res = Array.ofDim[A](n)
    REP(n)(i => res(i) = f(i + offset))
    res
  }


  def sumL(as: Array[Int]): Long = {
    var s = 0L
    REP(as.length)(i => s += as(i))
    s
  }

  def cumSum(as: Array[Int]) = {
    val cum = Array.ofDim[Long](as.length + 1)
    REP(as.length) { i =>
      cum(i + 1) = cum(i) + as(i)
    }
    cum
  }
}