Problem:
H: 魔法使いの塔

問題文

あなたが持っている魔導書には、 $N$ 個の魔法が載っています。

魔法には $1$ から $N$ までの番号がついていて、魔法 $i (1 \le i \le N)$ のコストははじめ整数 $A_i$ です。

あなたの目的は、魔導書に載っているすべての魔法を $1$ 回ずつ唱えることです。

魔法を唱えはじめる前に、あなたはクッキーを $K$ 枚食べることができます。クッキーを食べるのに時間はかかりません。

あなたはクッキーを $1$ 枚食べるたびに、コストが正の魔法を $1$ つ選び、そのコストを $1$ 下げることができます。

クッキーを食べたあと、あなたは魔法を唱え始めます。

あなたの MP ははじめ $M$ です。あなたは以下のどちらかを繰り返して、 $N$ 個の魔法を任意の順番で $1$ 回ずつ唱えます。

整数 $i (1 \le i \le N)$ を $1$ つ選び、魔法 $i$ を唱える。ただし、 現在の MP は魔法 $i$ のコスト以上でなければならない。

時間は経過しない。

MP を魔法 $i$ のコストだけ消費する。

休憩する。ただし、現在の MP を $m$ とすると、 $m < M$ でなければならない。

時間が $M - m$ 経過する。

MP を $1$ 回復する。

あなたが $N$ 個の魔法を任意の順番で $1$ 回ずつ唱えるためにかかる時間の最小値を求めてください。

制約

$1 \leq N \leq 10^5$

$1 \leq M \leq 10^6$

$0 \leq K \leq \sum_{i=1}^{N} A_i$

$1 \leq A_i \leq M$

入力はすべて整数である。

入力

入力は以下の形式で標準入力から与えられる。

$N$ $M$ $K$
$A_1$ $A_2$ $\ldots$ $A_N$

出力

$N$ 個の魔法を $1$ 回ずつ唱えるためにかかる時間の最小値を出力せよ。

入力例1

2 4 0
2 4

出力例1

3

どの魔法のコストも減らすことができないので、このまま魔法を唱えていくことにします。

まず、魔法 $1$ を唱えます。 MP を $2$ 消費するので、残りの MP は $4 - 2 = 2$ になります。

魔法 $2$ を唱えるには MP が $4$ 必要なので、このままでは魔法 $2$ を唱えることはできません。

休憩します。時間が $4 - 2 = 2$ 秒経過します。 MP を $1$ 回復するので、残りの MP は $2 + 1 = 3$ になります。

休憩します。時間が $4 - 3 = 1$ 秒経過します。 MP を $1$ 回復するので、残りの MP は $3 + 1 = 4$ になります。

魔法 $2$ を唱えます。 MP を $4$ 消費するので、残りの MP は $4 - 4 = 0$ になります。

以上より、時間を $2 + 1 = 3$ 秒かければ、魔法 $1,2$ を $1$ 回ずつ唱えることができます。
これより短い時間ですべての魔法を唱えることはできないので、求める答えは $3$ となります。

入力例2

3 9 6
2 3 9

出力例2

0

最終的な魔法のコストを $2, 2, 4$ とすると、休憩することなくすべての魔法を唱えることができます。

入力例3

3 16 2
6 9 9

出力例3

21

入力例4

2 1000000 0
1000000 1000000

出力例4

500000500000

答えは 32bit 整数で表せる範囲に収まらないことがあります。

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using static util;
using P = pair<int, int>;

class Program {
    static void Main(string[] args) {
        var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
        var solver = new Solver(sw);
        // var t = new Thread(solver.solve, 1 << 26); // 64 MB
        // t.Start();
        // t.Join();
        solver.solve();
        sw.Flush();
    }
}

class Solver {
    StreamWriter sw;
    Scan sc;
    void Prt(string a) => sw.WriteLine(a);
    void Prt<T>(IEnumerable<T> a) => Prt(string.Join(" ", a));
    void Prt(params object[] a) => Prt(string.Join(" ", a));
    public Solver(StreamWriter sw) {
        this.sw = sw;
        this.sc = new Scan();
    }

    public void solve() {
        int n, m;
        long k;
        sc.Multi(out n, out m, out k);
        var a = sc.LongArr;
        Array.Sort(a);
        if (a.Sum() - k <= m) {
            Prt(0);
            return;
        }
        int r = n;
        long ss = 0;
        while (true) {
            if (ss + a[r - 1] <= m) {
                ss += a[r - 1];
                --r;
            }
            else break;
        }
        Assert(r > 0);

        long ok = m + 1, ng = -1;
        while (ok > ng + 1) {
            long mid = (ok + ng) / 2;
            long sum = 0;
            for (int i = 0; i < r; i++)
            {
                sum += Math.Max(0, a[i] - mid);
            }
            if (sum <= k) {
                ok = mid;
            }
            else {
                ng = mid;
            }
        }
        // DBG(ok);
        for (int i = 0; i < r; i++)
        {
            if (a[i] > ok) {
                k -= a[i] - ok;
                a[i] = ok;
            }
        }
        Assert(k >= 0);

        for (int i = r - 1; i >= 0 ; i--)
        {
            if (k > 0 && a[i] > 0) {
                --k;
                --a[i];
            }
        }

        Assert(k == 0);
        Array.Sort(a);

        if (a[r - 1] + ss <= m) {
            k = m - ss - a[r - 1];
            a[r - 1] = m - ss;
            ss = m;
            --r;
            // ok = m + 1;
            ng = -1;
            while (ok > ng + 1) {
                long mid = (ok + ng) / 2;
                long sum = 0;
                for (int i = 0; i < r; i++)
                {
                    sum += Math.Max(0, a[i] - mid);
                }
                if (sum <= k) {
                    ok = mid;
                }
                else {
                    ng = mid;
                }
            }

            for (int i = 0; i < r; i++)
            {
                if (a[i] > ok) {
                    k -= a[i] - ok;
                    a[i] = ok;
                }
            }
            Assert(k >= 0);

            for (int i = r - 1; i >= 0 ; i--)
            {
                if (k > 0 && a[i] > 0) {
                    --k;
                    --a[i];
                }
            }
            Assert(k == 0);

        }




        Array.Sort(a);
        long ans = 0;
        long rem = a.Sum();
        long mp = m;
        Func<long, long, long> f = (frm, to) => {
            if (frm >= to) return 0;
            return (m - frm + m - to + 1) * (to - frm) / 2;
        };
        for (int i = 0; i < n; i++)
        {
            mp -= a[i];
            rem -= a[i];
            ans += f(mp, Math.Min(m, rem));
            mp = Math.Min(m, rem);
        }
        Prt(ans);




    }
}

class pair<T, U> : IComparable<pair<T, U>> {
    public T v1;
    public U v2;
    public pair() : this(default(T), default(U)) {}
    public pair(T v1, U v2) { this.v1 = v1; this.v2 = v2; }
    public int CompareTo(pair<T, U> a) {
        int c = Comparer<T>.Default.Compare(v1, a.v1);
        return c != 0 ? c : Comparer<U>.Default.Compare(v2, a.v2);
    }
    public override string ToString() => v1 + " " + v2;
    public void Deconstruct(out T a, out U b) { a = v1; b = v2; }
}
static class util {
    public static readonly int M = 1000000007;
    // public static readonly int M = 998244353;
    public static readonly long LM = 1L << 60;
    public static readonly double eps = 1e-11;
    public static void DBG(string a) => Console.Error.WriteLine(a);
    public static void DBG<T>(IEnumerable<T> a) => DBG(string.Join(" ", a));
    public static void DBG(params object[] a) => DBG(string.Join(" ", a));
    public static void Assert(params bool[] conds) {
        foreach (var cond in conds) if (!cond) throw new Exception();
    }
    public static pair<T, U> make_pair<T, U>(T v1, U v2) => new pair<T, U>(v1, v2);
    public static int CompareList<T>(IList<T> a, IList<T> b) where T : IComparable<T> {
        for (int i = 0; i < a.Count && i < b.Count; i++)
            if (a[i].CompareTo(b[i]) != 0) return a[i].CompareTo(b[i]);
        return a.Count.CompareTo(b.Count);
    }
    public static bool inside(int i, int j, int h, int w) => i >= 0 && i < h && j >= 0 && j < w;
    static readonly int[] dd = { 0, 1, 0, -1 };
    // static readonly string dstring = "RDLU";
    public static P[] adjacents(int i, int j)
        => Enumerable.Range(0, dd.Length).Select(k => new P(i + dd[k], j + dd[k ^ 1])).ToArray();
    public static P[] adjacents(int i, int j, int h, int w)
        => Enumerable.Range(0, dd.Length).Select(k => new P(i + dd[k], j + dd[k ^ 1]))
                                         .Where(p => inside(p.v1, p.v2, h, w)).ToArray();
    public static P[] adjacents(this P p) => adjacents(p.v1, p.v2);
    public static P[] adjacents(this P p, int h, int w) => adjacents(p.v1, p.v2, h, w);
    public static Dictionary<T, int> compress<T>(this IEnumerable<T> a)
        => a.Distinct().OrderBy(v => v).Select((v, i) => new { v, i }).ToDictionary(p => p.v, p => p.i);
    public static Dictionary<T, int> compress<T>(params IEnumerable<T>[] a) => compress(a.Aggregate(Enumerable.Union));
    public static T[] inv<T>(this Dictionary<T, int> dic) {
        var res = new T[dic.Count];
        foreach (var item in dic) res[item.Value] = item.Key;
        return res;
    }
    public static void swap<T>(ref T a, ref T b) where T : struct { var t = a; a = b; b = t; }
    public static void swap<T>(this IList<T> a, int i, int j) where T : struct { var t = a[i]; a[i] = a[j]; a[j] = t; }
    public static T[] copy<T>(this IList<T> a) {
        var ret = new T[a.Count];
        for (int i = 0; i < a.Count; i++) ret[i] = a[i];
        return ret;
    }
    public static void Deconstruct<T>(this IList<T> v, out T a) {
        a = v[0];
    }
    public static void Deconstruct<T>(this IList<T> v, out T a, out T b) {
        a = v[0]; b = v[1];
    }
    public static void Deconstruct<T>(this IList<T> v, out T a, out T b, out T c) {
        a = v[0]; b = v[1]; c = v[2];
    }
    public static void Deconstruct<T>(this IList<T> v, out T a, out T b, out T c, out T d) {
        a = v[0]; b = v[1]; c = v[2]; d = v[3];
    }
    public static void Deconstruct<T>(this IList<T> v, out T a, out T b, out T c, out T d, out T e) {
        a = v[0]; b = v[1]; c = v[2]; d = v[3]; e = v[4];
    }
}

class Scan {
    StreamReader sr;
    public Scan() { sr = new StreamReader(Console.OpenStandardInput()); }
    public Scan(string path) { sr = new StreamReader(path); }
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public string Str => sr.ReadLine().Trim();
    public pair<T, U> Pair<T, U>() {
        T a; U b;
        Multi(out a, out b);
        return new pair<T, U>(a, b);
    }
    public P P => Pair<int, int>();
    public int[] IntArr => StrArr.Select(int.Parse).ToArray();
    public long[] LongArr => StrArr.Select(long.Parse).ToArray();
    public double[] DoubleArr => StrArr.Select(double.Parse).ToArray();
    public string[] StrArr => Str.Split(new[]{' '}, StringSplitOptions.RemoveEmptyEntries);
    bool eq<T, U>() => typeof(T).Equals(typeof(U));
    T ct<T, U>(U a) => (T)Convert.ChangeType(a, typeof(T));
    T cv<T>(string s) => eq<T, int>()    ? ct<T, int>(int.Parse(s))
                       : eq<T, long>()   ? ct<T, long>(long.Parse(s))
                       : eq<T, double>() ? ct<T, double>(double.Parse(s))
                       : eq<T, char>()   ? ct<T, char>(s[0])
                                         : ct<T, string>(s);
    public void Multi<T>(out T a) => a = cv<T>(Str);
    public void Multi<T, U>(out T a, out U b) {
        var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]);
    }
    public void Multi<T, U, V>(out T a, out U b, out V c) {
        var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]);
    }
    public void Multi<T, U, V, W>(out T a, out U b, out V c, out W d) {
        var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]);
    }
    public void Multi<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e) {
        var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); e = cv<X>(ar[4]);
    }
}