import std.stdio, std.string, std.range, std.conv, std.array, std.algorithm, std.math, std.typecons, std.functional;
import std.container;

void main() {
    auto tmp = readln.split.to!(long[]);
    auto N = tmp[0], K = tmp[1];

    class Sushi {
        long t, d;
        bool inTree;
        this(long t, long d, bool inTree) {
            this.t = t;
            this.d = d;
            this.inTree = inTree;
        }
    }

    Sushi[] sushiList;
    foreach (i; 0..N) {
        tmp = readln.split.to!(long[]);
        sushiList ~= new Sushi(tmp[0], tmp[1],false);
    }
    sushiList = sushiList.sort!((a,b) => a.d < b.d).array;

    const totalNetaNum = sushiList
        .map!(s => s.t)
        .array
        .sort!((a,b) => a < b)
        .uniq
        .count;

    long[] currentNetaList = new long[N+1];
    long currentDelicious = 0;
    long currentNetaNum = 0;
    foreach (ref s; sushiList.retro.take(K)) {
        if (currentNetaList[s.t]++ == 0) currentNetaNum++;
        currentDelicious += s.d;
        s.inTree = true;
    }

    auto maxScore = currentDelicious + currentNetaNum^^2;

    while (currentNetaNum < min(K,totalNetaNum)) {
        auto removeTarget =
            sushiList
            .filter!(s => s.inTree)
            .filter!(s => currentNetaList[s.t] > 1)
            .front;

        currentDelicious -= removeTarget.d;
        currentNetaList[removeTarget.t]--;
        removeTarget.inTree = false;

        auto addTarget =
            sushiList
            .retro
            .filter!(s => !s.inTree)
            .filter!(s => currentNetaList[s.t] == 0)
            .front;

        currentDelicious += addTarget.d;
        currentNetaList[addTarget.t]++;
        addTarget.inTree = true;

        currentNetaNum++;

        maxScore = max(maxScore, currentDelicious + currentNetaNum^^2);
    }
    writeln(maxScore);
}

