Problem:
Score : 300 points

Problem Statement

N persons are standing in a row. The height of the i-th person from the front is A_i.

We want to have each person stand on a stool of some heights - at least zero - so that the following condition is satisfied for every person:

Condition: Nobody in front of the person is taller than the person. Here, the height of a person includes the stool.

Find the minimum total height of the stools needed to meet this goal.

Constraints

1 \leq N \leq 2\times 10^5

1 \leq A_i \leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 \ldots A_N

Output

Print the minimum total height of the stools needed to meet the goal.

Sample Input 1

5
2 1 5 4 3

Sample Output 1

4

If the persons stand on stools of heights 0, 1, 0, 1, and 2, respectively, their heights will be 2, 2, 5, 5, and 5, satisfying the condition.

We cannot meet the goal with a smaller total height of the stools.

Sample Input 2

5
3 3 3 3 3

Sample Output 2

0

Giving a stool of height 0 to everyone will work.

Solution in C# (.NET Core 3.1.201) (judge verdict: Wrong Answer)

namespace AtCoder
{
    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Text.RegularExpressions;

    class Program
    {
        static void Main()
        {
            var N = int.Parse(System.Console.ReadLine());
            var A = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();
            long sum = 0;
            for (int i = 1; i < N; i++)
            {
                if (A[i] - A[i-1]>0)
                {
                    sum += A[i] - A[i - 1];
                }
            }

            var ans = sum;
            Output(ans.ToString());
        }
        private static void Output(string str)
        {
            var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            Console.SetOut(sw);

            Console.WriteLine(str);

            Console.Out.Flush();
        }

    }

    static class Extentions
    {
        #region 拡張メソッド（string）

        public static string LeftB(this string stTarget, int iByteSize)
        {
            return MidB(stTarget, 1, iByteSize);
        }

        public static string MidB(this string stTarget, int iStart)
        {
            System.Text.Encoding hEncoding = System.Text.Encoding.GetEncoding("utf-8");
            byte[] bBytes = hEncoding.GetBytes(stTarget);

            return hEncoding.GetString(bBytes, iStart - 1, bBytes.Length - iStart + 1);
        }

        public static string MidB(this string stTarget, int iStart, int iByteSize)
        {
            System.Text.Encoding hEncoding = System.Text.Encoding.GetEncoding("utf-8");
            byte[] bBytes = hEncoding.GetBytes(stTarget);

            return hEncoding.GetString(bBytes, iStart - 1, iByteSize);
        }

        public static string RightB(this string stTarget, int iByteSize)
        {
            System.Text.Encoding hEncoding = System.Text.Encoding.GetEncoding("utf-8");
            byte[] bBytes = hEncoding.GetBytes(stTarget);

            return hEncoding.GetString(bBytes, bBytes.Length - iByteSize, iByteSize);
        }

        public static bool IsNullOrEmpty(this string str)
        {
            return string.IsNullOrEmpty(str);
        }

        /// <summary>
        /// カルチャに依存した比較、または大文字と小文字を区別しない比較などの序数による比較を指定できる Contains。
        /// </summary>
        /// <param name="value">対象文字列</param>
        /// <param name="partialValue">部分文字列</param>
        /// <param name="comparison">カルチャ、大文字と小文字の区別、および並べ替え規則を指定する StringComparison</param>
        /// <returns>一致する場合に true を返します。</returns>
        public static bool Contains(this string value, string partialValue, StringComparison comparison = 0)
        {
            return value.IndexOf(partialValue, comparison) >= 0;
        }

        public static bool IsNumeric(this string value)
        {
            return decimal.TryParse(value, out decimal d);
        }
        public static int ToInt32(this String number, int retValue = 0)
        {
            if (!number.IsNumeric()) return retValue;
            return int.Parse(number);
        }

        #endregion
    }

}


#region Template

/*
    using System;
    using System.Collections.Generic;
    using System.Linq;

    // 整数の入力========================================
    string[] input = Console.ReadLine().Split(' ');
    int a = int.Parse(input[0]);
    int b = int.Parse(input[1]);
    int c = int.Parse(Console.ReadLine());
    
    //配列操作========================================
    var a = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();

    int[] a = new int[n];
    for (int i = 0; i < n; i++)
    {
        a[i] = int.Parse(input2[i]);
    }
    
    Array.Sort(a);
    Array.Reverse(a);
    
    // 最小公倍数========================================
    public static decimal Lcm(decimal a, decimal b)
    {
        return a * b / Gcd(a, b);
    }

    // ユークリッドの互除法 ========================================
    public static decimal Gcd(decimal a, decimal b)
    {
        if (a < b)
        {
            // 引数を入替えて自分を呼び出す
            return Gcd(b, a);
        }
        while (b != 0)
        {
            var remainder = a % b;
            a = b;
            b = remainder;
        }
        return a;
    }

    // 全bit探索========================================
    
    // input桁のbit列で全探索を行う
    for (int x = 0; x < Math.Pow(2, input.Length); x++)
    {
        var array = new bool[input.Length];

        // 右からk桁目を取り出す
        for (int k = 0; k < input.Length; k++)
        {
            var y = (x >> k) & 1;
            array[k] = y==1;
        }
    }

    // DFS(深さ探索)========================================
    
    static void Main()
    {
        var input = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        var h = input[0];
        var w = input[1];
        var meiro = new char[w, h];
        var reached = new bool[w, h];
        var sh = 0;
        var sw = 0;
        var gh = 0;
        var gw = 0;
        for (int i = 0; i < h; i++)
        {
            var x = Console.ReadLine();
            for (int j = 0; j < w; j++)
            {
                meiro[j, i] = x[j];
                // スタートとゴール地点を退避
                if (x[j] == 's')
                {
                    sh = i;
                    sw = j;
                }
                if (x[j] == 'g')
                {
                    gh = i;
                    gw = j;
                }
            }
        }

        Search(sw, sh, meiro, reached);

        var ans = "No";
        if (reached[gw, gh] == true)
        {
            ans = "Yes";
        }
        Output(ans);
    }
    private static void Search(int x, int y, char[,] meiro, bool[,] reached)
    {
        // 壁や迷路の外なら脱出
        if (x < 0 || y < 0 || x > meiro.GetLength(0) - 1 || y > meiro.GetLength(1) - 1 || meiro[x, y] == '#') return;
        // 到達済みの場合も脱出
        if (reached[x, y] == true) return;
        // 到達記録
        reached[x, y] = true;

        Search(x + 1, y, meiro, reached);
        Search(x, y + 1, meiro, reached);
        Search(x - 1, y, meiro, reached);
        Search(x, y - 1, meiro, reached);
    }


    // DFS(深さ探索)========================================
    static void Main()
    {
        var input = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        var r = input[0];
        var c = input[1];
        var meiro = new char[r, c];
        var passed = new bool[r, c];
        var start = Console.ReadLine().Split(' ').Select(x => int.Parse(x) -1).ToList();
        var goal = Console.ReadLine().Split(' ').Select(x => int.Parse(x) -1).ToArray();
        for (int i = 0; i < r; i++)
        {
            var x = Console.ReadLine();
            for (int j = 0; j < c; j++)
            {
                meiro[i, j] = x[j];
            }
        }

        var numMoves = new int[r, c];
        var que = new Queue<int[]>();
        start.Add(0); // 深さ
        que.Enqueue(start.ToArray());
        BFS(que, passed, numMoves, meiro);

        Output(numMoves[goal[0], goal[1]].ToString());
    }
    private static void BFS(Queue<int[]> que, bool[,] passed, int[,] numMoves, char[,] meiro)
    {
        while (que.Count() > 0)
        {
            var p = que.Dequeue();

            var x = p[0];
            var y = p[1];
            // 壁や迷路の外なら脱出
            if (x < 0 || y < 0 || x > meiro.GetLength(0) - 1 || y > meiro.GetLength(1) - 1 || meiro[x, y] == '#') continue;
            // 到達済みの場合も脱出
            if (passed[x, y] == true) continue;
            // 到達記録
            passed[x, y] = true;
            numMoves[x, y] = p[2];
            que.Enqueue(new int[3] { x - 1, y    , p[2] + 1 });
            que.Enqueue(new int[3] { x + 1, y    , p[2] + 1 });
            que.Enqueue(new int[3] { x,     y - 1, p[2] + 1 });
            que.Enqueue(new int[3] { x,     y + 1, p[2] + 1 });
        }
    }

    //二分探索==============================================

    
        static void Main()
        {
            var n = Console.ReadLine().ToInt32();
            var a = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();
            var b = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();
            var c = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();

            long ans = 0;
            for (int i = 0; i < a.Count(); i++)
            {
                var aIdx = LowerBound(a, b[i]) - 1;
                if (aIdx < 0) continue;

                var cIdx = UpperBound(c, b[i]);
                if (cIdx > n - 1) continue;

                //組み合わせ
                long combi = (long)(aIdx + 1) * (long)(n - cIdx);
                ans += combi;
            }
            Output(ans.ToString());

        }
        private static int LowerBound(long[] arr, long target)
        {
            var min = 0;
            var max = arr.Length - 1;

            while (max >= min)
            {
                int mid = min + (max - min) / 2;
                if (arr[mid] < target)
                {
                    min = mid + 1;
                }
                else
                {
                    max = mid - 1;
                }
            }
            //target以上となる最初のインデックスを出力
            return min;
        }
        private static int UpperBound(long[] arr, long target)
        {
            var min = 0;
            var max = arr.Length - 1;

            while (max >= min)
            {
                var mid = (min + max) / 2;
                if (arr[mid] <= target)
                {
                    min = mid + 1;
                }
                else
                {
                    max = mid - 1;
                }
            }
            //target以上となる最初のインデックスを出力
            return min;
        }


    //出力========================================
    Console.WriteLine("");


    var sb = new StringBuilder();
    for (int j = 0; j<n; j++)
    {
        sb.AppendLine(a[j].ToString());
    }
    var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
    Console.SetOut(sw);
    Console.WriteLine(sb.ToString());
    Console.Out.Flush();
*/
#endregion