# Original solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1]*n  # 根のノードは限らないので注意

    def find(self, x):  # あるノードの親を探すためのメソッド
        if self.parents[x] < 0:  # 親の場合、要素の個数を負の値で保持している
            return x  # 自身が親であるということ
        else:
            self.parents[x] = self.find(self.parents[x])  # 再帰的に親を探しにいく
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)  # この変数xに格納されているものは必ず根のノード
        y = self.find(y)  # この変数yに格納されているものは必ず根のノード
        if x == y:
            return  # もし同じ親ならば何も起こらない

        if self.parents[x] > self.parents[y]:  # それぞれ、要素の個数が負で格納されている
            # yのグループの方が要素が多いの場合（yの方が値が小さいということは、負の世界では値が大きいため）
            x, y = y, x  # 必ずxの方が要素が多い状態にする

        self.parents[x] += self.parents[y]  # 負の値だが、これでいい
        self.parents[y] = x  # yは親ではなくなったため、新しい親であるxの値を正でもつ

    def size(self, x):
        return -self.parents[self.find(x)]  # 親まで辿ればグループの大きさが負で格納されているため、それにマイナスをつけてreturnする

    def same(self, x, y):
        return self.find(x) == self.find(y)  # 親が同じならTrueが返却される

    def members(self, x):  # この実装変じゃね？
        root = self.find(x)  # 親の値を取得する
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):  # 親であるノードの番号を全部取得する
        return [i for i in range(self.n) if self.find(i) < 0]

    def group_counts(self):
        return len(self.roots())  # グループの数を返す

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}  # 親のノード番号をキーにして、子のノードを対応させた辞書を返す

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())


N, M = list(map(int, input().split()))
graph = [[] for _ in range(N)]  # 隣接行列
brige_info = []
for _ in range(M):
    a, b = [int(x)-1 for x in list(map(int, input().split()))]
    brige_info.append((a, b))
    # graph[a].append(b)
    # graph[b].append(a)
ans = [int(N*(N-1))//2]*M
uf = UnionFind(N)

for i in reversed(list(range(1, M))):
    if uf.same(brige_info[i][0], brige_info[i][1]):
        ans[i-1] = ans[i]  # その橋を繋いでも不便さは改善されなかった、何も変わらない
        continue

    ans[i-1] = ans[i] - uf.size(brige_info[i][0]) * uf.size(brige_info[i][1])
    uf.union(brige_info[i][0], brige_info[i][1])

for i in range(M):
    print((ans[i]))


# Optimized solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]  # 親の値が更新され、更新された親の値が返る, 返るのは正の値

    def size(self, x):
        return -self.parents[self.find(x)]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.parents[x] > self.parents[y]:
            x, y = y, x  # 処理を行う上で、必ずxのグループの要素数の方が多くあってほしい
        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def same(self, x, y):
        return self.find(x) == self.find(y)


N, M = list(map(int, input().split()))
brige = []
for _ in range(M):
    a, b = [int(x)-1 for x in input().split()]
    brige.append((a, b))

uf = UnionFind(N)
ans = [int(N*(N-1)//2)]*M

for i in reversed(list(range(1, M))):
    if uf.same(brige[i][0], brige[i][1]):
        ans[i-1] = ans[i]
    else:
        ans[i-1] = ans[i] - uf.size(brige[i][0]) * uf.size(brige[i][1])
        uf.union(brige[i][0], brige[i][1])
for i in range(M):
    print((ans[i]))