Problem:
Score : 200 points

Problem Statement

There are K pieces of cakes.
Mr. Takahashi would like to eat one cake per day, taking K days to eat them all.

There are T types of cake, and the number of the cakes of type i (1 ≤ i ≤ T) is a_i.

Eating the same type of cake two days in a row would be no fun,
so Mr. Takahashi would like to decide the order for eating cakes that minimizes the number of days on which he has to eat the same type of cake as the day before.

Compute the minimum number of days on which the same type of cake as the previous day will be eaten.

Constraints

1 ≤ K ≤ 10000

1 ≤ T ≤ 100

1 ≤ a_i ≤ 100

a_1 + a_2 + ... + a_T = K

Input

The input is given from Standard Input in the following format:

K T
a_1 a_2 ... a_T

Output

Print the minimum number of days on which the same type of cake as the previous day will be eaten.

Sample Input 1

7 3
3 2 2

Sample Output 1

0

For example, if Mr. Takahashi eats cakes in the order of 2, 1, 2, 3, 1, 3, 1, he can avoid eating the same type of cake as the previous day.

Sample Input 2

6 3
1 4 1

Sample Output 2

1

There are 6 cakes.
For example, if Mr. Takahashi eats cakes in the order of 2, 3, 2, 2, 1, 2, he has to eat the same type of cake (i.e., type 2) as the previous day only on the fourth day.
Since this is the minimum number, the answer is 1.

Sample Input 3

100 1
100

Sample Output 3

99

Since Mr. Takahashi has only one type of cake, he has no choice but to eat the same type of cake as the previous day from the second day and after.

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

#pragma warning disable

class Segtree<T>
{
    int n;
    T[] tree;
    Func<T, T, T> f;
    T exnum;
    public Segtree(int m, Func<T, T, T> f, T ex)
    {
        this.f = f;
        this.exnum = ex;
        n = 1;
        while (n < m) n <<= 1;

        tree = new T[(n << 1) - 1];
        for (int i = 0; i < tree.Length; i++) tree[i] = ex;
    }
    public Segtree(int m, T ini, Func<T, T, T> f, T ex)
    {
        this.f = f;
        this.exnum = ex;
        n = 1;
        while (n < m) n <<= 1;

        tree = new T[(n << 1) - 1];
        for (int i = 0; i < tree.Length; i++) tree[i] = ini;
        for (int i = 0; i < m; ++i) update(i, ini);
    }
    public void update(int j, T x)
    {
        int i = j + n - 1;
        tree[i] = x;
        while (i > 0)
        {
            i = (i - 1) >> 1;
            tree[i] = f(tree[(i << 1) + 1], tree[(i << 1) + 2]);
        }
    }
    public T look(int i) { return tree[i + n - 1]; }

    // [s, t]
    public T run(int s, int t) { return query(s, t + 1, 0, 0, n); }
    T query(int s, int t, int k, int l, int r)
    {
        if (r <= s || t <= l) return exnum;
        if (s <= l && r <= t) return tree[k];

        return f(query(s, t, (k << 1) + 1, l, (l + r) >> 1), query(s, t, (k + 1) << 1, (l + r) >> 1, r));
    }
}

class PriorityQueue<T>
{
    private Comparison<T> comp;
    private List<T> list;
    private int count;
    public PriorityQueue() : this((x, y) => ((IComparable<T>)x).CompareTo(y)) { }
    public PriorityQueue(Comparison<T> comparison)
    {
        comp = comparison;
        list = new List<T>();
        count = 0;
    }
    public void Enqueue(T x)
    {
        var pos = count++;
        list.Add(x);
        while (pos > 0)
        {
            var p = (pos - 1) / 2;
            if (comp(list[p], x) <= 0) break;
            list[pos] = list[p];
            pos = p;
        }
        list[pos] = x;
    }
    public T Dequeue()
    {
        var value = list[0];
        var x = list[--count];
        list.RemoveAt(count);
        if (count == 0) return value;
        var pos = 0;
        while (pos * 2 + 1 < count)
        {
            var a = 2 * pos + 1;
            var b = 2 * pos + 2;
            if (b < count && comp(list[b], list[a]) < 0) a = b;
            if (comp(list[a], x) >= 0) break;
            list[pos] = list[a];
            pos = a;
        }
        list[pos] = x;
        return value;
    }
    public T Peek() { return list[0]; }
    public bool Any() { return count > 0; }
    public int Count() { return count; }
}

namespace Codeforces
{
    class Program
    {
        class mymath
        {
            static int Mod = 1000000007;
            public void setMod(int m) { Mod = m; }
            public bool isprime(long a)
            {
                if (a < 2) return false;
                for (long i = 2; i * i <= a; i++) if (a % i == 0) return false;
                return true;
            }
            public bool[] sieve(int n)
            {
                var isp = new bool[n + 1];
                for (int i = 2; i <= n; i++) isp[i] = true;
                for (int i = 2; i * i <= n; i++) if (isp[i]) for (int j = i * i; j <= n; j += i) isp[j] = false;
                return isp;
            }
            public List<int> getprimes(int n)
            {
                var prs = new List<int>();
                var isp = sieve(n);
                for (int i = 2; i <= n; i++) if (isp[i]) prs.Add(i);
                return prs;
            }
            public long[][] E(int n)
            {
                var ret = new long[n][];
                for (int i = 0; i < n; i++)
                {
                    ret[i] = new long[n];
                    ret[i][i] = 1;
                }
                return ret;
            }
            public long[][] powmat(long[][] A, long n)
            {
                if (n == 0) return E(A.Length);
                var t = powmat(A, n / 2);
                if ((n & 1) == 0) return mulmat(t, t);
                return mulmat(mulmat(t, t), A);
            }
            public long[] mulmat(long[][] A, long[] x)
            {
                int n = A.Length, m = x.Length;
                var ans = new long[n];
                for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) ans[i] = (ans[i] + x[j] * A[i][j]) % Mod;
                return ans;
            }
            public long[][] mulmat(long[][] A, long[][] B)
            {
                int n = A.Length, m = B[0].Length, l = B.Length;
                var ans = new long[n][];
                for (int i = 0; i < n; i++)
                {
                    ans[i] = new long[m];
                    for (int j = 0; j < m; j++) for (int k = 0; k < l; k++) ans[i][j] = (ans[i][j] + A[i][k] * B[k][j]) % Mod;
                }
                return ans;
            }
            public long[] addmat(long[] x, long[] y)
            {
                int n = x.Length;
                var ans = new long[n];
                for (int i = 0; i < n; i++) ans[i] = (x[i] + y[i]) % Mod;
                return ans;
            }
            public long[][] addmat(long[][] A, long[][] B)
            {
                int n = A.Length, m = A[0].Length;
                var ans = new long[n][];
                for (int i = 0; i < n; i++) ans[i] = addmat(A[i], B[i]);
                return ans;
            }
            public long powmod(long a, long b)
            {
                if (a >= Mod) return powmod(a % Mod, b);
                if (a == 0) return 0;
                if (b == 0) return 1;
                var t = powmod(a, b / 2);
                if ((b & 1) == 0) return t * t % Mod;
                return t * t % Mod * a % Mod;
            }
            public long inv(long a) { return powmod(a, Mod - 2); }
            public long gcd(long a, long b)
            {
                while (b > 0) { var t = a % b; a = b; b = t; }
                return a;
            }
            public long lcm(long a, long b) { return a * (b / gcd(a, b)); }
            public long Comb(int n, int r)
            {
                if (n < 0 || r < 0 || r > n) return 0;
                if (n - r < r) r = n - r;
                if (r == 0) return 1;
                if (r == 1) return n;
                var numerator = new int[r];
                var denominator = new int[r];
                for (int k = 0; k < r; k++)
                {
                    numerator[k] = n - r + k + 1;
                    denominator[k] = k + 1;
                }
                for (int p = 2; p <= r; p++)
                {
                    int pivot = denominator[p - 1];
                    if (pivot > 1)
                    {
                        int offset = (n - r) % p;
                        for (int k = p - 1; k < r; k += p)
                        {
                            numerator[k - offset] /= pivot;
                            denominator[k] /= pivot;
                        }
                    }
                }
                long result = 1;
                for (int k = 0; k < r; k++) if (numerator[k] > 1) result = result * numerator[k] % Mod;
                return result;
            }
        }

        const long InfL = 4011686018427387913L;
        static char[] sep = new char[] { ' ', '/' };


        //static int[] dx = { -1, 0, 1, -1, 1, -1, 0, -1 };
        //static int[] dy = { 1, 1, 1, 0, 0, -1, -1, -1 };

        static int[] dx = { -1, 0, 0, 1 };
        static int[] dy = { 0, 1, -1, 0 };


        /// <summary>
        /// basic dfs function
        /// </summary>
        /// 
        /* public class List_of_List<T> : List<List<T>> { }
        static int result = 0;

        static List<bool> visited = new List<bool>();
        static List_of_List<int> adj = new List_of_List<int>();

        static void dfs(int here)
        {
            if (here == n * m - 1)
            {
                result++;
                return;
            }
            visited[here] = true;

            for(int i = 0; i<adj[here].Count; i++)
            {
                int there = adj[here][i];
                if (!visited[there])
                    dfs(there);
                visited[there] = false;   
            }
        }

        static void dfsAll()
        {
            for(int i = 0; i<adj.Count; i++)
            {
                dfs(i);
            }
        }


        /* static int getInt => int.Parse(Console.ReadLine());
        static int[] getIntArr => Console.ReadLine().Trim().Split(sep).Select(a => int.Parse(a)).ToArray();
        static List<int> getIntList => Console.ReadLine().Trim().Split(sep).Select(a => int.Parse(a)).ToList<int>();
        static string getString => Console.ReadLine().Trim();
        static string[] getStrArr => Console.ReadLine().Trim().Split(sep);
        static List<string> getStrList => Console.ReadLine().Trim().Split(sep).ToList<string>();
        */
        static int m;
        static int n;
        static int[] input = new int[100001];



        static void Main(string[] args)
        {
            int[] first_input = Console.ReadLine().Trim().Split(sep).Select(a => int.Parse(a)).ToArray();
            int[] second_input = Console.ReadLine().Trim().Split(sep).Select(a => int.Parse(a)).ToArray();

            List<int> cake_count = new List<int>();
            for(int i = 0; i<second_input.Count(); i++)
            {
                cake_count.Add(second_input[i]);
            }

            cake_count.Sort();
            cake_count.Reverse();

            int result = 0;
            int cake_average = first_input[0] / first_input[1];
            for (int i = first_input[0]; i >= 0; i--) {
                if (cake_count.Count == 1)
                {
                    result = cake_count[0] - 1;
                    break;
                }
                if (cake_count.Count == 0) break;
                if(cake_count[0] > 0 && cake_count[1] > 0)
                {
                    cake_count[0]--;
                    cake_count[1]--;
                    if (cake_count[1] == 0) cake_count.RemoveAt(1);
                    if (cake_count[0] == 0) cake_count.RemoveAt(0);
                }
                cake_count.Sort();
                cake_count.Reverse();
            }

            Console.WriteLine(result);

        }

        /*
        /// <summary>
        /// 이분 매칭 알고리즘
        /// </summary>

        static bool[,] adj; // 연결 리스트. 이분 매칭이기 때문에 bool 형식이다. 혹-시라도 타임아웃이 뜬다면 인접리스트로 바꿔볼 것. 조금 빨라진다.
        static List<bool> visited; // 왼쪽의 한 정점에서 오른쪽의 모든 정점으로 방문 기록을 정리하는 리스트
        static List<int> m_match; // 왼쪽에 있는 정점들의 집합
        static List<int> n_match; // 오른쪽에 있는 정점들의 집합


        static bool dfs(int a) // 왼쪽 정점 a 에서 오른쪽 정점으로 가는 경로를 찾는다
        {
            if (visited[a]) return false;
            visited[a] = true;
            for (int b = 0; b < n; b++)
            {
                if (adj[a, b]) // 왼쪽 정점 a 에서 오른쪽 정점중 b에 연결할 수 있는 경우
                {
                    if (n_match[b] == -1 || dfs(n_match[b])) // b가 이미 매칭되어 있다면 n_match[b]에서 시작되는 증가경로를 찾는다
                    {
                        // 증가 경로를 발견한 경우 a와 b를 매치시키고 true를 반환한다
                        m_match[a] = b;
                        n_match[b] = a;
                        return true;
                    }
                }
            }
            return false;
        }

        static int bipartite_match()
        {
            m_match = Enumerable.Repeat(-1, m).ToList(); // 왼쪽에 있는 정점들의 각 원소가 오른쪽에 있는 어떤 정점과 대응되는지 기록하는 리스트
            n_match = Enumerable.Repeat(-1, n).ToList(); // 오른쪽에 있는 정점들의 각 원소가 왼쪽에 있는 어떤 정점과 대응되는지 기록하는 리스트

            int size = 0; // 몇 쌍이 대응되는지 기록하는 변수
            for (int start = 0; start < m; start++) // m_match (왼쪽에 있는 정점들 집합) 의 모든 원소에 대해 dfs 실시
            {
                visited = Enumerable.Repeat(false, m).ToList(); // 모든 점에 대해 초기화 (방문하지 않음으로 표시)

                if (dfs(start)) size++; // 각 왼쪽 정점에서 dfs를 실시해서 갈 수 있는 경로가 있다면 경로의 개수를 1 늘린다
            }
            return size;
        }
        */

        /*
        /// <summary>
        /// 네트워크 유량 문제용 포드-풀커슨 알고리즘
        /// </summary>

        const int INF = 987654321;
        static int v; // 정점의 수. source와 sink가 있으므로 감안해서 계산
        static int max_v;
        static int[,] capacity, flow;
        // capacity[u,v] = u에서 v로 보낼 수 있는 용량, flow[u,v] = u에서 v로 흘러가는 유량 (반대방향인 경우 음수)

        // flow[,] 를 계산하고 총 유량을 반환하는 함수
        static int networkFlow(int source, int sink)
        {
            flow = new int[max_v, max_v]; // flow 배열의 초기화
            int totalFlow = 0;
            while (true)
            {
                List<int> parent = Enumerable.Repeat(-1, max_v).ToList();
                Queue<int> q = new Queue<int>();
                parent[source] = source;
                q.Enqueue(source);
                while (q.Count != 0 && parent[sink] == -1)
                {
                    int here = q.Dequeue();
                    for (int there = 0; there < v; there++)
                    {
                        if (capacity[here, there] - flow[here, there] > 0 && parent[there] == -1)
                        {
                            q.Enqueue(there);
                            parent[there] = here;
                        }
                    }
                }

                if (parent[sink] == -1) break;

                int amount = INF;
                for(int p = sink; p != source; p = parent[p])
                {
                    amount = Math.Min(capacity[parent[p], p] - flow[parent[p], p], amount);
                }
                for(int p = sink; p != source; p = parent[p])
                {
                    flow[parent[p], p] += amount;
                    flow[p, parent[p]] -= amount;
                }
             
                totalFlow += amount;
            }
            return totalFlow;
        }
        */
    }
}