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];

    alias Sushi = Tuple!(long, "t", long, "d");
    Sushi[] sushiList;
    foreach (i; 0..N) {
        tmp = readln.split.to!(long[]);
        sushiList ~= Sushi(tmp[0], tmp[1]);
    }
    auto tree = redBlackTree!(true, Sushi)([]);
    foreach (s; sushiList.sort!((a,b) => a.d > b.d).take(K)) {
        tree.insert(s);
    }


    auto totalNetaNum = sushiList
        .sort!((a,b) => a.t < b.t)
        .group!((a,b) => a.t == b.t)
        .count;

    auto currentNetaNum = tree
        .array
        .sort!((a,b) => a.t < b.t)
        .group!((a,b) => a.t == b.t)
        .count;

    auto maxScore = tree[].map!(s => s.d).sum + currentNetaNum^^2;

    while (currentNetaNum < totalNetaNum) {
        auto removeTarget = 
            tree
            .array
            .sort!((a,b) => a.t < b.t)
            .group!((a,b) => a.t == b.t)
            .filter!(v => v[1] > 1)
            .map!(v => v[0])
            .minElement!(s => s.d);
        
        tree.removeKey(removeTarget);

        auto addTarget = sushiList
            .filter!(s => !tree[].canFind(s))
            .filter!(s => tree[].all!(s2 => s.t != s2.t))
            .maxElement!(s => s.d);

        tree.insert(addTarget);

        currentNetaNum++;

        maxScore = max(maxScore, tree[].map!(s => s.d).sum + currentNetaNum^^2);
    }
    writeln(maxScore);
}

