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

void main() {
    auto tmp = readln.split.to!(long[]);
    const N = tmp[0], M = tmp[1];
    auto nodeList = N.iota.map!(i => new Node(i)).array;
    auto bridgeList = M.iota.map!(_ => readln.split.to!(long[]));

    long[] result = [N*(N-1)/2];
    foreach_reverse(i; 0..M) {
        auto bridge = bridgeList[i];
        auto nodeA = nodeList[bridge[0]-1];
        auto nodeB = nodeList[bridge[1]-1];

        if (nodeA.find() == nodeB.find()) {
            result ~= result.back;
            continue;
        }

        const sizeA = nodeA.getSize;
        const sizeB = nodeB.getSize;
        result ~= result.back - sizeA * sizeB;

        unite(nodeA, nodeB);
    }
    result.popBack;
    result.retro.each!writeln;
}

class Node {
    long value;
    long size;
    Node parent;

    this(long value) { this.value = value; this.size = 1; }

    Node root() {
        if (parent is null) return this;
        auto result = parent.root;
        this.parent = result;
        return result;
    }

    long find() {
        return root.value;
    }

    long getSize() {
        return root.size;
    }
}

void unite(Node u, Node v) {
    auto up = u.root;
    auto vp = v.root;

    vp.parent = up;
    up.size += vp.size;
}
