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: Accepted)

//
// ABC176C
// URL : https://atcoder.jp/contests/abc176/tasks/abc176_c
// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Security.Cryptography.X509Certificates;

namespace AtCoder.Template.ABC176C
{
    class Solver
    {
        public static readonly long MOD_CONST = 1000000007;//(long)Math.Pow(10, 9) + 7;

        public static void Main(string[] args)
        {
            //出力高速化
            var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            Console.SetOut(sw);
            var solver = new Solver();
            solver.Solve();
            Console.Out.Flush();
        }
        public void Solve()
        {
            int n = int.Parse(Console.ReadLine());
            long[] An = Console.ReadLine().Split(' ').Select(_inputStr => long.Parse(_inputStr)).ToArray();

            long sum = 0;
            long max = An[0];
#if false
            var finalAn = new long[n];
            finalAn[0] = An[0];
#endif
            for(int i = 1; i < n; ++i)
            {
                long bias = 0;
                if(An[i] < max)
                {
                    bias = max - An[i];
                    sum += bias;
                }
                else
                {
                    max = An[i];
                    bias = 0;
                }
#if false
                finalAn[i] = bias + An[i];
#endif
            }
#if false
            Console.WriteLine(string.Join(" ", finalAn));
#endif
            Console.WriteLine(sum);
        }

        //---------------------------------------------------------------------------------
#region MyLib
        /// <summary>
        /// string -> List<char>に分解する。1文字がListの1要素
        /// </summary>
        /// <param name="a"></param>
        /// <returns></returns>
        public static List<char> separeteToList(string a)
        {
            var l = new List<char>(a.Length);
            foreach (char x in a)
            {
                l.Add(x);
            }
            return l;
        }
        /// <summary>
        /// List<char> -> stringに合成する
        /// </summary>
        /// <param name="l"></param>
        /// <returns></returns>
        public static string combineCharList(List<char> l)
        {
            var ans = new StringBuilder();
            foreach (char x in l)
            {
                ans.Append(x);
            }
            return ans.ToString();
        }

        /// <summary>
        /// Aの文字をなるべくCorrectに合うように並びかえる。当然Correctにしかない文字もあるので、その場合はAの適当な文字で置き換える
        /// 例)
        /// A       = abcde, eppstein
        /// Corrent = acfbe, pipeline
        /// ans     = acdbe, pspetine
        /// </summary>
        /// <param name="A"></param>
        /// <param name="Correct"></param>
        public static List<char> FillChar(List<char> A, List<char> Correct)
        {
            char Empty = ' ';
            var ARemain = new List<char>(A);
            var ans = new List<char>(A.Count);
            for (int i = 0; i < Correct.Count; ++i)
            {
                //Aの文字をなるべくCorrectに合うように、ansの文字を決める
                int foundPos = ARemain.FindIndex(x => x == Correct[i]);
                if (foundPos != -1)//文字がCorrectの中で見つかったら
                {
                    char found = ARemain[foundPos];
                    ans.Add(found);
                    ARemain.Remove(found);//使った文字は除外
                }
                else//Aにない文字もある。後で使わなかったAの適当な文字で埋める
                {
                    ans.Add(Empty);
                }
            }
            //Aにない文字がCorrectにあったら、Aの残りの文字で適当に埋める
            for (int i = 0; i < A.Count; ++i)
            {
                if (ans[i] == Empty)
                {
                    ans[i] = ARemain.First();
                    ARemain.RemoveAt(0);
                }
            }
            return ans;
        }


        /// <summary>
        /// リストから、重複したものを除外したリストを新規に作成する
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="src"></param>
        /// <param name="dst"></param>
        public static void getDistinctList<T>(List<T> src, out List<T> dst)
        {
            var iter = src.Distinct();
            dst = new List<T>();
            foreach (var item in iter)
            {
                dst.Add(item);
            }
        }

        /// <summary>
        /// グラフ系
        /// </summary>
        public class Node
        {
            public Node(long val){
                this.Value = val;
                this.Children = new List<Node>();
            }

            public Node(long val, List<Node> children)
            {
                this.Value = val;
                this.Children = children;
            }

            public long Value { get; set; }
            public List<Node> Children { get; set; }
        }

        /// <summary>
        /// Clamping
        /// </summary>
        /// <typeparam name="T">比較型</typeparam>
        /// <param name="x">clampしたい値</param>
        /// <param name="min">最小値</param>
        /// <param name="max">最大値</param>
        /// <returns>clamp済みの値</returns>
        public static T Clamp<T>(T x, T min, T max) where T : IComparable<T>
        {
            if (x.CompareTo(min) < 0) { return min; }
            else if (x.CompareTo(max) > 0) { return max; }
            else return x;
            //return Math.Max(Math.Min(x, max), min);
        }

        /// <summary>
        /// 指定された底log_baseでの, 対数を計算
        /// </summary>
        /// <param name="x"></param>
        /// <param name="log_base">指定の底</param>
        /// <returns></returns>
        public static double LogBase(double x, double log_base)
        {
            //log_b(N) = log_a(N) / log_a(B)より
            return Math.Log(x) / Math.Log(log_base);
        }

        /// <summary>
        /// 初項a, 公差d, 項数nの数列の和
        /// </summary>
        /// <param name="n">求めたいところ</param>
        /// <returns>初項からxまで足した値</returns>
        static long SumSeries(long a, long d, long n)
        {
            return (2 * a + (n - 1) * d) * n / 2;
        }
        /// <summary>
        /// 累積和の配列を計算する
        /// Sum[ a[0], a[i] )がs[i+1]に入っている
        /// s[0]  : 0                //一切和を取らない場合
        /// s[1]  : ls[0]            //a[0]   + s[0] = a[0]
        /// s[2]  : ls[1] + s[1]     //a[1]   + a[0]
        /// ...
        /// s[N]  : ls[N-1] + s[N-1] //a[N-1] + ... + a[0]
        /// s[N+1]: ls[N] + s[N]     //a[N]   + ... + a[0]
        /// 
        /// 例: [1, 7)の和(a[1] + ... + a[6])
        /// s[1] = a[0] //[0, 1)
        /// s[7] = a[0] + a[1] + ... + a[6] //[0, 7)
        /// よってs[7] - s[1]);
        /// </summary>
        /// <param name="ls">計算したい配列</param>
        /// <returns>累積和配列</returns>
        static List<long> AggregateSumList(List<long> a)
        {
            var s = new List<long>(a.Count + 1);
            if (a.Count == 0)
            {
                return s;
            }
            s.Add(0);//s[0] = 0
            for (int i = 0; i < a.Count; ++i)
            {
                s.Add(a[i] + s[i]);
            }
            return s;
        }


        /// <summary>
        /// 与えられた数が素数かどうかを計算する
        /// </summary>
        /// <param name="num">対象数</param>
        /// <returns>true:素数, false:素数ではない(合成数)</returns>
        public static bool isPrime(int num)
        {
            if (num < 2) return false;
            else if (num == 2) return true;
            else if (num % 2 == 0) return false;

            double sqrtNum = Math.Sqrt(num);
            for (int i = 3; i <= sqrtNum; i += 2)
            {
                if (num % i == 0)
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 素因数分解
        /// </summary>
        /// <param name="n"></param>
        /// <returns>keyが素数、valueがその素数の登場回数</returns>
        public static Dictionary<long, long> PrimeFactorization(long n)
        {
            var result = new Dictionary<long, long>();
            //初めの素数2から割っていく
            for (long p = 2; p * p <= n; p++)
            {
                //割り切れないなら、素因数に含まれてない
                if (n % p != 0) continue;
                long count = 0;

                // 割り続ける
                while (n % p == 0)
                {
                    count++;
                    n /= p;
                }

                result[p] = count;
            }

            // 素数が残っている場合
            if (n != 1) result[n] = 1;
            return result;
        }


        /// <summary>
        /// 順列mPnを計算する
        /// </summary>
        /// <param name="m"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        public static long Permutation(long m, long n)
        {
            long ret = 1;
            for (var i = 0; i < n; ++i)
            {
                ret *= m - i;
            }
            return ret;
        }
        /// <summary>
        /// 組み合わせmCnを計算する
        /// </summary>
        /// <param name="m"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        public static long Combination(long m, long n)
        {
            if (m == n || n == 0)
            {
                return 1;
            }
            long ans = 1;
            for (var i = 1; i <= n; ++i)
            {
                ans = ans * (m - i + 1) / i;
            }
            return ans;
        }

        static long Gcd(long m, long n)
        {
            if (n == 0) return m;
            return Gcd(n, m % n);
        }

        static long Lcm(long m, long n)
        {
            var gcd = Gcd(m, n);
            //return (m * n) / gcd;
            return m / gcd * n;//桁あふれ対策
        }
#endregion MyLib
    }
}