Problem:
Trampoline

A plurality of trampolines are arranged in a line at 10 m intervals. Each trampoline has its own maximum horizontal distance within which the jumper can jump safely. Starting from the left-most trampoline, the jumper jumps to another trampoline within the allowed jumping range. The jumper wants to repeat jumping until he/she reaches the right-most trampoline, and then tries to return to the left-most trampoline only through jumping. Can the jumper complete the roundtrip without a single stepping-down from a trampoline?

Write a program to report if the jumper can complete the journey using the list of maximum horizontal reaches of these trampolines. Assume that the trampolines are points without spatial extent.

Input

The input is given in the following format.

N
d_1
d_2
:
d_N

The first line provides the number of trampolines N (2 ≤ N ≤ 3 × 105). Each of the subsequent N lines gives the maximum allowable jumping distance in integer meters for the i-th trampoline d_i (1 ≤ d_i ≤ 106).

Output

Output "yes" if the jumper can complete the roundtrip, or "no" if he/she cannot.

Sample Input 1

4
20
5
10
1

Sample Output 1

no

Sample Input 2

3
10
5
10

Sample Output 2

no

Sample Input 3

4
20
30
1
20

Sample Output 3

yes

Solution in C# (judge verdict: Memory Limit Exceeded)

using System.Collections.Generic;
using System;

public class PriorityQueue<T> where T : IComparable
{
    private IComparer<T> _comparer = null;
    private int _type = 0;
    private T[] _heap;
    private int _sz = 0;
    private int _count = 0;
    /// <summary>
    /// Priority Queue with custom comparer
    /// </summary>
    public PriorityQueue(int maxSize, IComparer<T> comparer)
    {
        _heap = new T[maxSize];
        _comparer = comparer;
    }

    /// <summary>
    /// Priority queue
    /// </summary>
    /// <param name="maxSize">max size</param>
    /// <param name="type">0: asc, 1:desc</param>
    public PriorityQueue(int maxSize, int type = 0)
    {
        _heap = new T[maxSize];
        _type = type;
    }
    private int Compare(T x, T y)
    {
        if (_comparer != null) return _comparer.Compare(x, y);
        return _type == 0 ? x.CompareTo(y) : y.CompareTo(x);
    }
    public void Push(T x)
    {
        _count++;
        //node number
        var i = _sz++;
        while (i > 0)
        {
            //parent node number
            var p = (i - 1) / 2;

            if (Compare(_heap[p], x) <= 0) break;

            _heap[i] = _heap[p];
            i = p;
        }
        _heap[i] = x;
    }
    public T Pop()
    {
        _count--;
        T ret = _heap[0];
        T x = _heap[--_sz];

        int i = 0;
        while (i * 2 + 1 < _sz)
        {
            //children
            int a = i * 2 + 1;
            int b = i * 2 + 2;

            if (b < _sz && Compare(_heap[b], _heap[a]) < 0) a = b;

            if (Compare(_heap[a], x) >= 0) break;

            _heap[i] = _heap[a];
            i = a;
        }
        _heap[i] = x;
        return ret;
    }
    public int Count()
    {
        return _count;
    }
    public T Peek()
    {
        return _heap[0];
    }
    public bool Contains(T x)
    {
        for (int i = 0; i < _sz; i++) if (x.Equals(_heap[i])) return true;
        return false;
    }
    public void Clear()
    {
        while (this.Count() > 0) this.Pop();
    }
    public IEnumerator<T> GetEnumerator()
    {
        var ret = new List<T>();
        while (this.Count() > 0)
        {
            ret.Add(this.Pop());
        }
        foreach (var r in ret)
        {
            this.Push(r);
            yield return r;
        }
    }
    public T[] ToArray()
    {
        T[] array = new T[_sz];
        int i = 0;
        foreach (var r in this)
        {
            array[i++] = r;
        }
        return array;
    }
}
public struct Edge
{
    public int to { get; set; }
    public int d { get; set; }
}
public class Node : IComparable
{
    public int id { get; set; }
    public int d { get; set; }
    public int CompareTo(object obj)
    {
        var x = (Node)obj;
        if (this.d > x.d) return 1;
        else if (this.d == x.d) return 0;
        else return -1;
    }
}

public class Hello
{
    public const int INF = 999999999;
    public static void Main()
    {
        var n = int.Parse(Console.ReadLine().Trim());
        var a = new List<Edge>[n];
        for (int i = 0; i < n; i++) a[i] = new List<Edge>();
        for (int i = 0; i < n; i++)
        {
            string[] line = Console.ReadLine().Trim().Split(' ');
            var p = int.Parse(line[0]);
            var emax = p / 10;
            if (emax == 0) continue;
            for (int j =  1; j <=  emax; j++)
            {
                if (i + j <= n - 1) a[i].Add(new Edge { to = i + j ,d = 0});
                if (i - j >= 0) a[i].Add(new Edge { to = i - j ,d = 0});
            }
        }
        var mind = new int[n];
        for (int i = 0; i < n; i++) mind[i] = INF;
        goDijk(a, 0, n, mind);
        if (mind[ n - 1] == INF) { Console.WriteLine("no"); goto end; }
        for (int i = 0; i < n; i++) mind[i] = INF;
        goDijk(a, n-1, n, mind);
        if (mind[0] == INF) { Console.WriteLine("no"); goto end; }
        Console.WriteLine("yes");
        end:;
    }
    public static void goDijk(List<Edge>[] aa, int r, int n, int[] mind)
    {
        var pq = new PriorityQueue<Node>(n + 10000, 0);
        pq.Push(new Node { id = r, d = 0 });
        while (pq.Count() > 0)
        {
            var targ = pq.Pop();
            var nowd = targ.d;
            var nowid = targ.id;
            if (mind[nowid] < nowd) continue;
            mind[nowid] = nowd;
            foreach (var x in aa[nowid])
                if (nowd + x.d < mind[x.to])
                    pq.Push(new Node { id = x.to, d = nowd + x.d });
        }
    }
}