Problem:
Score : 400 points

Problem Statement

There are N pieces of sushi. Each piece has two parameters: "kind of topping" t_i and "deliciousness" d_i.
You are choosing K among these N pieces to eat.
Your "satisfaction" here will be calculated as follows:

The satisfaction is the sum of the "base total deliciousness" and the "variety bonus".

The base total deliciousness is the sum of the deliciousness of the pieces you eat.

The variety bonus is x*x, where x is the number of different kinds of toppings of the pieces you eat.

You want to have as much satisfaction as possible.
Find this maximum satisfaction.

Constraints

1 \leq K \leq N \leq 10^5

1 \leq t_i \leq N

1 \leq d_i \leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N K
t_1 d_1
t_2 d_2
.
.
.
t_N d_N

Output

Print the maximum satisfaction that you can obtain.

Sample Input 1

5 3
1 9
1 7
2 6
2 5
3 1

Sample Output 1

26

If you eat Sushi 1,2 and 3:

The base total deliciousness is 9+7+6=22.

The variety bonus is 2*2=4.

Thus, your satisfaction will be 26, which is optimal.

Sample Input 2

7 4
1 1
2 1
3 1
4 6
4 5
4 5
4 5

Sample Output 2

25

It is optimal to eat Sushi 1,2,3 and 4.

Sample Input 3

6 5
5 1000000000
2 990000000
3 980000000
6 970000000
6 960000000
4 950000000

Sample Output 3

4900000016

Note that the output may not fit into a 32-bit integer type.

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using static System.Console;
using static System.Math;
using static Macro;
using static Extension;
using static LinqExtension;
using static HelpExtension;
class AC {
    /*------------------------------------------------------------------*/
    int N, K;
    int[] t, d;
    
    struct Sushi : IComparable<Sushi> {
        public long T;
        public long D;
        public Sushi(long t, long d) {
            T = t;
            D = d;
        }
        public int CompareTo(Sushi o) {
            return this.D.CompareTo(o.D);
        }
    }

    void Solve() {
        io.i(out N, out K);
        io.ini(out t, out d, N);

        var maxScore = 0L;
        var dScore = 0L;
        var tDic = new Dictionary<long, int>();

        var sushi = t.Zip(d, (t, d) => new Sushi(t, d)).Sort().Rev();
        
        var lowPoint = new PriorityQueue<Sushi>();
        var highPoint = new PriorityQueue<Sushi>();

        sushi.Take(K).Iter(x => {
            var t = x.T;
            var d = x.D;
            if (!tDic.ContainsKey(t)) tDic[t] = 0;
            tDic[t]++;
            lowPoint.Enqueue(x);
            dScore += d;
        });
        
        maxScore = dScore + (tDic.Keys.Count()) * (tDic.Keys.Count());

        sushi.Skip(K).Iter(x => {
            highPoint.Enqueue(x);
        });

        while (lowPoint.Any && highPoint.Any) {
            var l = lowPoint.Dequeue();
            if (tDic[l.T] == 1) continue;
            tDic[l.T]--;
            var h = highPoint.Dequeue();
            if (tDic.ContainsKey(h.T)) continue;
            tDic[h.T] = 1;
            dScore -= l.D;
            dScore += h.D;
            maxScore = Max(maxScore, dScore + (tDic.Keys.Count()) * (tDic.Keys.Count()));
        }

        maxScore.Prt();
    }

    /*------------------------------------------------------------------*/
    void Test() {
        //--- TEST ---//
    }
    public static void Main(string[] args) => new AC().Stream();
    const int INF = int.MaxValue / 2;
    IO io = new IO();
    private void Stream() {
        /*
        var exStdIn = new System.IO.StreamReader("stdin.txt");
        SetIn(exStdIn);
        Test();
        */
        Solve();
        io.Flush();
    }
}
class IO {
    #region INPUT
    #region FastRead
    private const int Size = 1 << 12;
    private readonly Stream _stream = OpenStandardInput();
    private readonly byte[] _buffer = new byte[Size];
    private int _ptr = 0, _buffLen = 0;
    private bool HasNextByte() {
        if (_ptr < _buffLen) return true;
        _ptr = 0;
        _buffLen = _stream.Read(_buffer, 0, Size);
        return _buffLen > 0;
    }
    private byte ReadByte() {
        if (HasNextByte()) return _buffer[_ptr++];
        else
            //inputの末尾の改行がないとerror
            throw new EndOfStreamException();
    }
    private bool IsAscii(int c) => '!' <= c && c <= '~';
    private char NextChar() {
        var b = ReadByte();
        while (!IsAscii(b)) b = ReadByte();
        return (char)b;
    }
    private string Next() {
        var sb = new StringBuilder();
        for (var b = NextChar(); IsAscii(b); b = (char)ReadByte()) sb.Append(b);
        return sb.ToString();
    }
    public string String => Next();
    public char Char => NextChar();
    public int Int => int.Parse(Next());
    public long Long => long.Parse(Next());
    public double Double => double.Parse(Next());
    #endregion
    #region LazyRead
    private void scan<T>(ref T x) {
        if (x is int) __refvalue(__makeref(x), int) = int.Parse(Next());
        else if (x is long) __refvalue(__makeref(x), long) = long.Parse(Next());
        else if (x is double) __refvalue(__makeref(x), double) = double.Parse(Next());
        else if (x is char) __refvalue(__makeref(x), char) = NextChar();
        else __refvalue(__makeref(x), string) = Next();
    }
    public void i<T>(out T t) {
        t = default(T);
        scan(ref t);
    }
    public void i<T, TU>(out T t, out TU u) {
        i(out t);
        i(out u);
    }
    public void i<T, TU, TV>(out T t, out TU u, out TV v) {
        i(out t, out u);
        i(out v);
    }
    public void i<T, TU, TV, TW>(out T t, out TU u, out TV v, out TW w) {
        i(out t, out u);
        i(out v, out w);
    }
    public void i<T, TU, TV, TW, TX>(out T t, out TU u, out TV v, out TW w, out TX x) {
        i(out t, out u, out v);
        i(out w, out x);
    }
    public void i<T, TU, TV, TW, TX, TY>(out T t, out TU u, out TV v, out TW w, out TX x, out TY y) {
        i(out t, out u, out v);
        i(out w, out x, out y);
    }
    public void ini<T>(out T[] a, int n) {
        a = new T[n];
        for (int i = 0; i < n; ++i) i<T>(out a[i]);
    }
    public void ini<T, TU>(out T[] a, out TU[] b, int n) {
        a = new T[n];
        b = new TU[n];
        for (int i = 0; i < n; ++i) i<T, TU>(out a[i], out b[i]);
    }
    public void ini<T, TU, TV>(out T[] a, out TU[] b, out TV[] c, int n) {
        a = new T[n];
        b = new TU[n];
        c = new TV[n];
        for (var i = 0; i < n; ++i) i<T, TU, TV>(out a[i], out b[i], out c[i]);
    }
    public void ini<T, TU, TV, TW>(out T[] a, out TU[] b, out TV[] c, out TW[] d, int n) {
        a = new T[n];
        b = new TU[n];
        c = new TV[n];
        d = new TW[n];
        for (var i = 0; i < n; ++i) i<T, TU, TV, TW>(out a[i], out b[i], out c[i], out d[i]);
    }
    public void ini<T>(out T[,] a, int h, int w) {
        a = new T[h, w];
        for (int i = 0; i < h; ++i) for (int j = 0; j < w; ++j) i<T>(out a[i, j]);
    }
    #endregion
    #endregion
    #region OUTPUT
    private readonly StreamWriter _sw = new StreamWriter(OpenStandardOutput()) {
#if DEBUG
        AutoFlush = true
#else
        AutoFlush = false
#endif
    };
    public void Flush() => Out.Flush();
    public void YN(bool f) => yn(f, "YES", "NO");
    public void Yn(bool f) => yn(f, "Yes", "No");
    public void yn(bool f, string y = "yes", string n = "no") => WriteLine(f ? y : n);
    #endregion
    public IO() { SetOut(_sw); }
}
static class Macro {
    public static void FOR(int a, int b, int n, Action<int> f) {
        for (var i = a; i < b; i += n) {
            try {
                f(i);
            } catch (IndexOutOfRangeException e) {
#if DEBUG
                WriteLine($"IndexOutOfRange at [{i}]");
#endif
            }
        }
    }
    public static void FOR(int a, int b, Action<int> f) => FOR(a, b, 1, f);
    public static void REP(int a, Action<int> f) => FOR(0, a, 1, f);
    public static void REP(int a, int n, Action<int> f) => FOR(0, a, n, f);
    public static void FOREQ(int a, int b, Action<int> f) => FOR(a, b + 1, 1, f);
    public static void FOREQ(int a, int b, int n, Action<int> f) => FOR(a, b + 1, n, f);
    public static void REPEQ(int a, Action<int> f) => FOR(0, a + 1, 1, f);
    public static void REPEQ(int a, int n, Action<int> f) => FOR(0, a + 1, n, f);
    public static T MIN<T>(params T[] xs) => xs.Min();
    public static T MAX<T>(params T[] xs) => xs.Max();
    public struct Item_2<T, U> {
        public T Item1;
        public U Item2;
        public Item_2(T item1, U item2) {
            Item1 = item1;
            Item2 = item2;
        }
    }
    public struct Item_3<T, U, V> {
        public T Item1;
        public U Item2;
        public V Item3;
        public Item_3(T item1, U item2, V item3) {
            Item1 = item1;
            Item2 = item2;
            Item3 = item3;
        }
    }
    public static IEnumerable<Item_2<T, U>> ZIP<T, U>(IEnumerable<T> x, IEnumerable<U> y)
        => x.Zip(y, (i1, i2) => new Item_2<T, U>(i1, i2));

    public static IEnumerable<Item_3<T, U, V>> ZIP<T, U, V>(
        IEnumerable<T> xs,
        IEnumerable<U> ys,
        IEnumerable<V> zs) {
        using (var eX = xs.GetEnumerator())
        using (var eY = ys.GetEnumerator())
        using (var eZ = zs.GetEnumerator()) {
            while (eX.MoveNext() && eY.MoveNext() && eZ.MoveNext()) {
                yield return new Item_3<T, U, V>(eX.Current, eY.Current, eZ.Current);
            }
        }
    }

    public static IEnumerable<T> Hoge<T>(IEnumerable<T> xs, params IEnumerable<T>[] xxs)
        => xs.Concat(xxs.SelectMany(x => x));
}
static class Extension {
    public static void Rep(this int a, Action<int> f) => FOR(0, a, 1, f);
    public static void Rep(this int a, int n, Action<int> f) => FOR(0, a, n, f);
    public static void RepEQ(this int a, Action<int> f) => FOR(0, a + 1, 1, f);
    public static void RepEQ(this int a, int n, Action<int> f) => FOR(0, a + 1, n, f);
    public static void Prt<T>(this T x) => WriteLine(x);
    public static void Prt<T>(this IEnumerable<T> xs) => xs.Iter(x => WriteLine(x));
    public static void Prt_<T>(this IEnumerable<T> xs) {
        xs.Iter(x => Write($"{x} "));
        WriteLine();
    }
    public static bool IsOdd(this int x) => x % 2 != 0;
    public static bool IsOdd(this long x) => x % 2 != 0;
}
static class LinqExtension {
    public struct IndexedValue<T> {
        public int Index;
        public T Value;
        public IndexedValue(int index, T value) {
            this.Index = index;
            this.Value = value;
        }
        public override string ToString() {
            return string.Format("Index: {0}, Value: {1}", Index, Value);
        }
    }
    public struct Pair<T> {
        public T Fst;
        public T Snd;
        public Pair(T fst, T snd) {
            Fst = fst;
            Snd = snd;
        }
        public override string ToString() {
            return string.Format("({0}, {1})", Fst, Snd);
        }
    }
    public static IEnumerable<IndexedValue<T>> Indexed<T>(this IEnumerable<T> source) {
        return source.Select((value, index) => new IndexedValue<T>(index, value));
    }

    public static void Iter<T>(this IEnumerable<T> source, Action<T> action) {
        foreach (var s in source) action(s);
    }

    public static IEnumerable<Pair<T>> PairWise<T>(this IEnumerable<T> source) {
        return source.Zip(source.Skip(1), (fst, snd) => new Pair<T>(fst, snd));
    }

    private static IEnumerable<T> Init<T>(int size, Func<int, T> f) {
        for (var i = 0; i < size; ++i) yield return f(i);
    }

    public static IEnumerable<IEnumerable<T>> Windowed<T>(this IEnumerable<T> source, int size) {
        var tmpArr = new T[size];
        var r = size - 1;
        var i = 0;
        using (var e = source.GetEnumerator()) {
            while (e.MoveNext()) {
                tmpArr[i] = e.Current;
                i = (i + 1) % size;
                if (r == 0) yield return Init<T>(size, j => tmpArr[(i + j) % size]);
                else r--;
            }
        }
    }

    public static T Then<T>(this T source, Action<T> action) {
        if (source == null) return source;
        action(source);
        return source;
    }

    public static IEnumerable<T> Sort<T>(this IEnumerable<T> source) => source.OrderBy(x => x);

    public static IEnumerable<T> Rev<T>(this IEnumerable<T> source) => Sort(source).Reverse();

    public static IEnumerable<T> DistinctBy<T, U>(this IEnumerable<T> source, Func<T, U> groupBy, Func<IGrouping<U, T>, T> selectBy)
        => source.GroupBy(groupBy).Select(selectBy);
    public static IEnumerable<T> DistinctBy<T, U>(this IEnumerable<T> source, Func<T, U> groupBy) => source.DistinctBy(groupBy, x => x.First());

}
static class HelpExtension {
    public class PriorityQueue<T> where T : IComparable<T> {
        private List<T> heap;
        private bool isAsc;
        public T Peek => heap[0];
        public int Count { get; private set; }
        public bool Any => Count > 0;
        public bool Empty => !Any;

        public PriorityQueue(bool isAsc = true) {
            this.isAsc = isAsc;
            Count = 0;
            heap = new List<T>();
        }

        public void Enqueue(T item) {
            heap.Add(item);
            var i = Count++;
            while (i > 0) {
                var p = (i - 1) / 2;
                if (Compare(heap[p], item) <= 0) break;
                heap[i] = heap[p];
                i = p;
            }
            heap[i] = item;
        }

        public T Dequeue() {
            var ret = heap[0];
            var x = heap[--Count];
            var i = 0;
            while ((i << 1) + 1 < Count) {
                var a = (i << 1) + 1;
                var b = (i << 1) + 2;
                if (b < Count && Compare(heap[b], heap[a]) < 0) a = b;
                if (Compare(heap[a], x) >= 0) break;
                heap[i] = heap[a];
                i = a;
            }
            heap[i] = x;
            heap.RemoveAt(Count);
            return ret;
        }

        private int Compare(T x, T y) => isAsc ? x.CompareTo(y) : y.CompareTo(x);
    }
}