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)

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Numerics;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Diagnostics;
using static System.Math;
using static System.Array;
using static AtCoder.Cout;
using static AtCoder.Tool;
using static AtCoder.ModInt;
namespace AtCoder
{
    class AC
    {
        const int MOD = 1000000007;
        //const int MOD = 998244353;
        const int INF = int.MaxValue / 2;
        const long SINF = long.MaxValue / 3;
        const double EPS = 1e-8;
        static readonly int[] dI = { 0, 1, 0, -1, 1, -1, -1, 1 };
        static readonly int[] dJ = { 1, 0, -1, 0, 1, 1, -1, -1 };
        static void Main(string[] args)
        {
            //var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }; Console.SetOut(sw);

            var th = new Thread(Run, 1 << 26);
            th.Start();
            th.Join();

            //Run();
            Console.Out.Flush();
        }
        static void Run()
        {
            int Testcase = 1;
            //Testcase = Cin.Int;
            for (var _ = 0; _ < Testcase; _++) Solve();
        }
        static void Solve()
        {
            int N = Cin.Int;
            var A = Cin.ReadSplitLong;
            long ans = 0;
            for(var i = 1; i < N; i++)
            {
                ans += Max(0, A[i - 1] - A[i]);
                A[i] = Max(A[i - 1], A[i]);
            }
            OutL(ans);
        }
        
        public struct Edge
        {
            public int from;

            public int to;
            public long dist;

            public Edge(int t, long c)
            {
                from = -1;
                to = t;
                dist = c;
            }
            public Edge(int f, int t, long c)
            {
                from = f;
                to = t;
                dist = c;
            }
        }
    }
    struct ModInt
    {
        public long value;
        private const int MOD = 1000000007;
        //private const int MOD = 998244353;
        public ModInt(long value) { this.value = value; }
        public static implicit operator ModInt(long a)
        {
            var ret = a % MOD;
            return new ModInt(ret < 0 ? (ret + MOD) : ret);
        }
        public static ModInt operator +(ModInt a, ModInt b) => (a.value + b.value);
        public static ModInt operator -(ModInt a, ModInt b) => (a.value - b.value);
        public static ModInt operator *(ModInt a, ModInt b) => (a.value * b.value);
        public static ModInt operator /(ModInt a, ModInt b) => a * Modpow(b, MOD - 2);

        public static ModInt operator <<(ModInt a, int n) => (a.value << n);
        public static ModInt operator >>(ModInt a, int n) => (a.value >> n);
        public static ModInt operator ++(ModInt a) => a.value + 1;
        public static ModInt operator --(ModInt a) => a.value - 1;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ModInt Modpow(ModInt a, long n)
        {
            var k = a;
            ModInt ret = 1;
            while (n > 0)
            {
                if ((n & 1) != 0) ret *= k;
                k *= k;
                n >>= 1;
            }
            return ret;
        }
        private static readonly List<long> Factorials = new List<long>() { 1 };
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ModInt Fac(long n)
        {
            for (var i = Factorials.Count(); i <= n; i++)
            {
                Factorials.Add((Factorials[i - 1] * i) % MOD);
            }
            return Factorials[(int)n];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ModInt nCr(long n, long r)
        {
            if (n < 0 || r < 0) return 0;
            return n < r ? 0 : Fac(n) / (Fac(r) * Fac(n - r));
        }
        public static explicit operator int(ModInt a) => (int)a.value;
    }
    public class Rolling_Hash
    {
        const ulong m30 = (1UL << 30) - 1;
        const ulong m31 = (1UL << 31) - 1;
        const ulong MOD = (1UL << 61) - 1;
        const ulong Pl = (MOD << 1) << 1;
        private uint B;
        private string S;
        ulong[] hash;
        ulong[] pw;

        public Rolling_Hash(string str)
        {
            S = str;
            B = (uint)new Random().Next(1 << 12 + 1, int.MaxValue);
            int L = S.Length;
            hash = new ulong[L + 1];
            pw = new ulong[L + 1];
            hash[0] = 0;
            pw[0] = 1;
            for (var i = 0; i < L; i++)
            {
                hash[i + 1] = CalcMod(Mul(hash[i], B) + S[i]);
                pw[i + 1] = CalcMod(Mul(pw[i], B));
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ulong GetHashValue(int idx) => hash[idx];
        [MethodImpl(MethodImplOptions.AggressiveInlining)]//segment [l,r]
        public ulong Hash_fold(int l, int r) => CalcMod(Pl + hash[r + 1] - Mul(hash[l], pw[r - l + 1]));
        [MethodImpl(MethodImplOptions.AggressiveInlining)]//segment[start,start+len-1]
        public ulong Hash_sub(int start, int len) => CalcMod(Pl + hash[start + len] - Mul(hash[start], pw[len]));
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ulong[] GetHashArray() => hash;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        ulong Mul(ulong a, ulong b)
        {
            ulong au = a >> 31;
            ulong ad = a & m31;
            ulong bu = b >> 31;
            ulong bd = b & m31;
            ulong mid = ad * bu + au * bd;
            ulong midu = mid >> 30;
            ulong midd = mid & m30;
            return au * bu * 2 + midu + (midd << 31) + ad * bd;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        ulong CalcMod(ulong x)
        {
            ulong xu = x >> 61;
            ulong xd = x & MOD;
            ulong res = xu + xd;
            if (res >= MOD) res -= MOD;
            return res;
        }
    }
    public class Priority_Queue<T>
    {
        private List<T> Q;
        private readonly Comparison<T> Func_Compare;
        public Priority_Queue(Comparison<T> comp)
        {
            Func_Compare = comp;
            Q = new List<T>();
        }
        private void PushHeap(List<T> list, T item)
        {
            int n = list.Count();
            list.Add(item);

            while (n != 0)
            {
                int pIndex = (n - 1) / 2;

                if (Func_Compare(list[n], list[pIndex]) < 0)
                {
                    Swap(Q, n, pIndex);
                }
                else { break; }

                n = pIndex;
            }
        }
        private void PopHeap(List<T> list)
        {
            int n = list.Count() - 1;
            list[0] = list[n];
            list.RemoveAt(n);

            int cur = 0;
            int comp;

            while (2 * cur + 1 <= n - 1)
            {
                int c1 = 2 * cur + 1;
                int c2 = 2 * (cur + 1);
                if (c1 == n - 1)
                {
                    comp = c1;
                }
                else
                {

                    comp = Func_Compare(list[c1], list[c2]) < 0 ? c1 : c2;
                }

                if (Func_Compare(list[cur], list[comp]) > 0)
                {
                    Swap(Q, cur, comp);
                }
                else { break; }

                cur = comp;
            }
        }
        private void Swap(List<T> list, int a, int b)
        {
            T keep = list[a];
            list[a] = list[b];
            list[b] = keep;
        }

        public void Enqueue(T value)
        {
            PushHeap(Q, value);
        }

        public T Dequeue()
        {
            T ret = Q[0];
            PopHeap(Q);
            return ret;
        }

        public T Peek()
        {
            return Q[0];
        }

        public int Count()
        {
            return Q.Count();
        }
        public bool Any()
        {
            return Q.Any();
        }
    }
    public class SegmentTree<T>
    {
        //1-indexed type
        int n;
        T[] Tree;
        Func<T, T, T> f;
        T ex;
        int L;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public SegmentTree(int size, Func<T, T, T> fun, T exvalue)
        {
            ex = exvalue;
            f = fun;
            n = 1;
            while (n < size) n <<= 1;
            Tree = new T[n << 1];
            L = (n << 1) - 1;
            for (var i = 0; i <= L; i++) Tree[i] = ex;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public SegmentTree(int size, Func<T, T, T> fun, T exvalue, T[] initial)
        {
            ex = exvalue;
            n = 1; while (n < size) n <<= 1;
            f = fun;
            Tree = new T[n << 1];
            L = (n << 1) - 1;
            for (var i = 0; i <= L; i++) Tree[i] = (n <= i && i <= n + initial.Length - 1) ? initial[i - n] : ex;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Set_All()
        {
            for (var i = n - 1; i >= 1; i--) Tree[i] = f(Tree[i << 1], Tree[(i << 1) | 1]);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Assign(int idx, T nxt) => Tree[idx + n] = nxt;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Update(int idx)
        {
            int now = idx + n;
            while (now > 1)
            {
                now >>= 1;
                Tree[now] = f(Tree[now << 1], Tree[now << 1 | 1]);
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Query_Update(int idx, T nxt)
        {
            Assign(idx, nxt); Update(idx);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Query_Update_func(int idx, T y)
        {
            Assign(idx, f(Peek(idx), y)); Update(idx);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T Query_Fold(int l, int r)
        {
            int L = n + l;
            int R = n + r;
            T vL = ex, vR = ex;
            while (L < R)
            {
                if (L % 2 == 1)
                {
                    vL = f(vL, Tree[L]);
                    L++;
                }
                if (R % 2 == 1)
                {
                    vR = f(Tree[R - 1], vR);
                    R--;
                }
                L >>= 1;
                R >>= 1;
            }
            return f(vL, vR);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T Peek(int idx) => Tree[idx + n];
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Display(int len)
        {
            for (var i = 0; i < len; i++) Console.Write($"{Tree[i + n]} ");
            Console.WriteLine();
        }
    }
    public class UnionFind
    {
        private int[] parent;
        private int[] rank;
        private int[] size;
        public UnionFind(int n)
        {
            parent = new int[n];
            rank = new int[n];
            size = new int[n];
            for (var i = 0; i < n; i++)
            {
                parent[i] = i;
                rank[i] = 0;
                size[i] = 1;
            }
        }

        public int Root(int x)
        {
            return parent[x] == x ? x : parent[x] = Root(parent[x]);
        }

        public bool SameRoot(int x, int y)
        {
            return Root(x) == Root(y);
        }

        public void Unite(int x, int y)
        {
            x = Root(x);
            y = Root(y);
            if (x == y) { return; }

            if (rank[x] < rank[y])
            {
                parent[x] = y;
                size[y] += size[x];
                size[x] = 0;
            }
            else
            {
                parent[y] = x;
                if (rank[x] == rank[y]) { rank[x]++; }
                size[x] += size[y];
                size[y] = 0;
            }
        }

        public int SizeOf(int x)
        {
            return size[Root(x)];
        }

    }
    static class Cin
    {
        public static string[] ReadSplit => Console.ReadLine().Split();
        public static int[] ReadSplitInt => ConvertAll(Console.ReadLine().Split(), int.Parse);
        public static long[] ReadSplitLong => ConvertAll(Console.ReadLine().Split(), long.Parse);
        public static double[] ReadSplit_Double => ConvertAll(Console.ReadLine().Split(), double.Parse);
        public static string Str => Console.ReadLine();
        public static int Int => int.Parse(Console.ReadLine());
        public static long Long => long.Parse(Console.ReadLine());
        public static double Double => double.Parse(Console.ReadLine());
        public static T Conv<T>(string input)
        {
            if (typeof(T).Equals(typeof(ModInt)))
            {
                return (T)(dynamic)(long.Parse(input));
            }
            return (T)Convert.ChangeType(input, typeof(T));
        }
        public static void Input<T>(out T a) => a = Conv<T>(Console.ReadLine());
        public static void Input<T, U>(out T a, out U b)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); }
        public static void Input<T, U, V>(out T a, out U b, out V c)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); }
        public static void Input<T, U, V, W>(out T a, out U b, out V c, out W d)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); d = Conv<W>(q[3]); }
        public static void Input<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); d = Conv<W>(q[3]); e = Conv<X>(q[4]); }
    }
    static class Cout
    {
        public static void OutL(object s) => Console.WriteLine(s);
        public static void Out_Sep<T>(IEnumerable<T> s) => Console.WriteLine(string.Join(" ", s));
        public static void Out_Sep<T>(IEnumerable<T> s, string sep) => Console.WriteLine(string.Join($"{sep}", s));
        public static void Out_Sep(params object[] s) => Console.WriteLine(string.Join(" ", s));
        public static void Out_One(object s) => Console.Write($"{s} ");
        public static void Out_One(object s, string sep) => Console.Write($"{s}{sep}");
        public static void Endl() => Console.WriteLine();
    }
    public static class Tool
    {
        static public void Initialize<T>(ref T[] array, T initialvalue)
        {
            array = ConvertAll(array, x => initialvalue);
        }
        static public void Swap<T>(ref T a, ref T b)
        {
            T keep = a;
            a = b;
            b = keep;
        }
        static public void Display<T>(T[,] array2d, int n, int m)
        {
            for (var i = 0; i < n; i++)
            {
                for (var j = 0; j < m; j++)
                {
                    Console.Write($"{array2d[i, j]} ");
                }
                Console.WriteLine();
            }
        }
        static public long Gcd(long a, long b)
        {
            if (a == 0 || b == 0) return Max(a, b);
            return a % b == 0 ? b : Gcd(b, a % b);
        }
        static public long LPow(int a, int b) => (long)Pow(a, b);
        static public bool Bit(long x, int dig) => ((1L << dig) & x) != 0;
        static public int Sig(long a) => a == 0 ? 0 : (int)(a / Abs(a));
    }
}