import std.stdio, std.range, std.conv, std.string, std.array, std.functional, std.math;
import std.algorithm.comparison, std.algorithm.iteration, std.algorithm.mutation, std.algorithm.searching, std.algorithm.setops, std.algorithm.sorting;
import std.container.binaryheap;
import std.typecons; 

struct Pair{
    long a;
    long b;
}
void main()
{
    auto input = readln().strip.split.to!(long[]);
    const N = input[0];
    const M = input[1];
    auto list = uninitializedArray!(Pair[])(M);
    foreach(i; 0..M) {
        input = readln().strip.split.to!(long[]);
        list[i] = Pair(input[0], input[1]);
    }

    long[] resList;
    UnionFind unionFind = new UnionFind(N+1);
    long count = N*(N-1)/2;
    foreach_reverse(e; list) {
        if(unionFind.same(e.a, e.b))
        {
            resList ~= count;
            continue;
        }

        resList ~= count;
        count -= unionFind.count(e.a)*unionFind.count(e.b);
        unionFind.unite(e.a, e.b);
    }
    foreach_reverse(res; resList) {
        writeln(res);
    }
}

class UnionFind{
    private long[] list;

    this(long n)
    {
        list.length = n;
        list.fill(-1);
    }

    void unite(long a, long b)
    {
        list[root(a)] += list[root(b)];
        list[root(b)] = root(a);
    }

    bool same(long a, long b)
    {
        return root(a) == root(b);
    }

    long count(long n)
    {
        return -list[root(n)];
    }

    private long root(long n)
    {
        if(list[n] < 0)
        {
            return n;
        }

        return list[n] = root(list[n]);
    }
}