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

void main() {
    auto tmp = readln.split.to!(long[]);
    const N = tmp[0], M = tmp[1];
    auto bridgeList = new long[2][M];
    foreach (i; 0..M) {
        tmp = readln.split.to!(long[]);
        const A = tmp[0], B = tmp[1];
        bridgeList[i] = [A-1,B-1];
    }

    auto islandList = [iota(N).array];

    foreach (i; 0..M) {
        auto bridge = bridgeList[i];
        auto targetIsland = islandList.find!(island => island.canFind(bridge[0])).front;
        auto newIsland = targetIsland.remake(bridgeList[i+1..$]);
        islandList = islandList.filter!(island => island != targetIsland).array ~ newIsland;

        long cnt = 0;
        foreach (j; 0..islandList.length) {
            foreach (k; j+1..islandList.length) {
                cnt += islandList[j].length * islandList[k].length;
            }
        }
        writeln(cnt);
    }
}


long[][2] remake(long[] node, long[2][] bridge) {
    long[] nodeA, nodeB;
    foreach (n; node) {
        if (nodeA.empty) {
            nodeA ~= n;
            continue;
        }
        if (isConnected(nodeA[0], n, bridge)) {
            nodeA ~= n;
        } else {
            nodeB ~= n;
        }
    }
    return [nodeA, nodeB];
}

bool isConnected(long nodeA, long nodeB, long[2][] bridge) {
    bool[long] memory;
    long[] stack;

    stack ~= nodeA;
    memory[nodeA] = true;
    do {
        long c = stack.back;
        stack.popBack();

        if (c == nodeB) return true;

        const candidates =
            bridge.map!(b =>
                b[0] == c ? [b[1]] :
                b[1] == c ? [b[0]] : [])
            .join
            .filter!(n => n !in memory)
            .array;

        candidates.each!(c => memory[c] = true);
        stack ~= candidates;
    } while (!stack.empty);

    return false;
}
