# Union-Find木を使って書き直し



# Union-Find木（サイズ付き）

class UnionFind():

    def __init__(self, n):  # n要素で初期化　初めは全ての頂点が別々の木の根

        self.parent = [None] * n # 親

        self.rank = [None] * n   # 木の深さ

        self._size = [1] * n # 要素が属する集合の大きさ（根の要素のみ参照すること）

        for i in range(n):

            self.parent[i] = i

            self.rank[i] = 0



    # 木の根を求める

    def root_of(self, x):

        children = [x]

        while self.parent[x] != x:

            x = self.parent[x]

            children.append(x)



        for ch in children: # 根の子供として張りなおす

            self.parent[ch] = x



        return x



    # xとyの属する集合を併合

    def unite(self, x, y):

        rx = self.root_of(x)

        ry = self.root_of(y)

        if rx == ry:

            return

        if self.rank[rx] < self.rank[ry]: # ランクの小さい木から大きい木の根に辺を張る

            self.parent[rx] = ry  # rxをryの子とする

            self._size[ry] += self._size[rx]

        else:

            self.parent[ry] = rx

            self._size[rx] += self._size[ry]

            if self.rank[rx] == self.rank[ry]:

                self.rank[rx] += 1



    # 同じ集合に属するかどうか

    def is_same(self, x, y):

        return self.root_of(x) == self.root_of(y)



    # 頂点xが属する集合のサイズ

    def size(self, x):

        return self._size[self.root_of(x)]



# 入力

N, M = [int(x) for x in input().split()]

A = [None] * M

B = [None] * M

for i in range(M):

    A[i], B[i] = [int(x) - 1 for x in input().split()]





# 島同士が全く繋がっていない状態からスタート

# M-1番目, M-2番目, ..., , 2番目, 1番目の橋の順に橋をかけていく

inconv = [-1] * (M - 1) + [N * (N - 1) // 2]    # 不便さ



uf = UnionFind(N)



for i in range(M - 1, 0, -1):

    # i番目の橋をかける

    if not uf.is_same(A[i], B[i]):

        size_a = uf.size(A[i]) # A[i]が属する集合の大きさ

        size_b = uf.size(B[i]) # B[i]が属する集合の大きさ

        inconv[i - 1] = inconv[i] - size_a * size_b

        uf.unite(A[i], B[i])

    else:

        inconv[i - 1] = inconv[i]



for i in range(M):

    print((inconv[i]))

# 20-08-12再トライ

import sys

input = sys.stdin.readline



class UnionFind():

    def __init__(self, n):

        self.rank = [0] * n

        self.par = list(range(n))

        self._size = [1] * n  # 木の根のみ有効、集合に属する要素数



    def find(self, x):

        ch = []

        while self.par[x] != x:

            ch.append(x)

            x = self.par[x]

        for c in ch:

            self.par[c] = x



        return x



    def union(self, x, y):

        rx = self.find(x)

        ry = self.find(y)

        if rx == ry:

            return

        if self.rank[rx] >= self.rank[ry]:

            self.par[ry] = rx

            self._size[rx] += self._size[ry]

            if self.rank[rx] == self.rank[ry]:

                self.rank[rx] += 1

        else:

            self.par[rx] = ry

            self._size[ry] += self._size[rx]



    def same(self, x, y):

        return self.find(x) == self.find(y)



    def size(self, x):

        return self._size[self.find(x)]



N, M = [int(x) for x in input().split()]

E = [tuple(int(x) - 1 for x in input().split()) for _ in range(M)]

inconv = [0] * M

inconv[M - 1] = N * (N - 1) // 2

uf = UnionFind(N)



for i in range(M - 1, 0, -1):

    a = E[i][0]

    b = E[i][1]

    inconv[i - 1] = inconv[i]

    if uf.same(a, b):

        continue

    inconv[i - 1] -= uf.size(a) * uf.size(b)

    uf.union(a, b)



for i in range(M):

    print((inconv[i]))
# Union-Find木を使って書き直し
# Union-Find木（サイズ付き）
class UnionFind:
    def __init__(self, n):  # n要素で初期化　初めは全ての頂点が別々の木の根
        self.parent = [None] * n  # 親
        self.rank = [None] * n  # 木の深さ
        self._size = [1] * n  # 要素が属する集合の大きさ（根の要素のみ参照すること）
        for i in range(n):
            self.parent[i] = i
            self.rank[i] = 0

    # 木の根を求める
    def root_of(self, x):
        children = [x]
        while self.parent[x] != x:
            x = self.parent[x]
            children.append(x)
        for ch in children:  # 根の子供として張りなおす
            self.parent[ch] = x
        return x

    # xとyの属する集合を併合
    def unite(self, x, y):
        rx = self.root_of(x)
        ry = self.root_of(y)
        if rx == ry:
            return
        if self.rank[rx] < self.rank[ry]:  # ランクの小さい木から大きい木の根に辺を張る
            self.parent[rx] = ry  # rxをryの子とする
            self._size[ry] += self._size[rx]
        else:
            self.parent[ry] = rx
            self._size[rx] += self._size[ry]
            if self.rank[rx] == self.rank[ry]:
                self.rank[rx] += 1

    # 同じ集合に属するかどうか
    def is_same(self, x, y):
        return self.root_of(x) == self.root_of(y)

    # 頂点xが属する集合のサイズ
    def size(self, x):
        return self._size[self.root_of(x)]


# 入力
N, M = [int(x) for x in input().split()]
A = [None] * M
B = [None] * M
for i in range(M):
    A[i], B[i] = [int(x) - 1 for x in input().split()]
# 島同士が全く繋がっていない状態からスタート
# M-1番目, M-2番目, ..., , 2番目, 1番目の橋の順に橋をかけていく
inconv = [-1] * (M - 1) + [N * (N - 1) // 2]  # 不便さ
uf = UnionFind(N)
for i in range(M - 1, 0, -1):
    # i番目の橋をかける
    if not uf.is_same(A[i], B[i]):
        size_a = uf.size(A[i])  # A[i]が属する集合の大きさ
        size_b = uf.size(B[i])  # B[i]が属する集合の大きさ
        inconv[i - 1] = inconv[i] - size_a * size_b
        uf.unite(A[i], B[i])
    else:
        inconv[i - 1] = inconv[i]
for i in range(M):
    print((inconv[i]))

# 20-08-12再トライ
import sys

input = sys.stdin.readline


class UnionFind:
    def __init__(self, n):
        self.rank = [0] * n
        self.par = list(range(n))
        self._size = [1] * n  # 木の根のみ有効、集合に属する要素数

    def find(self, x):
        ch = []
        while self.par[x] != x:
            ch.append(x)
            x = self.par[x]
        for c in ch:
            self.par[c] = x
        return x

    def union(self, x, y):
        rx = self.find(x)
        ry = self.find(y)
        if rx == ry:
            return
        if self.rank[rx] >= self.rank[ry]:
            self.par[ry] = rx
            self._size[rx] += self._size[ry]
            if self.rank[rx] == self.rank[ry]:
                self.rank[rx] += 1
        else:
            self.par[rx] = ry
            self._size[ry] += self._size[rx]

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

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


N, M = [int(x) for x in input().split()]
E = [tuple(int(x) - 1 for x in input().split()) for _ in range(M)]
inconv = [0] * M
inconv[M - 1] = N * (N - 1) // 2
uf = UnionFind(N)
for i in range(M - 1, 0, -1):
    a = E[i][0]
    b = E[i][1]
    inconv[i - 1] = inconv[i]
    if uf.same(a, b):
        continue
    inconv[i - 1] -= uf.size(a) * uf.size(b)
    uf.union(a, b)
for i in range(M):
    print((inconv[i]))

-# Union-Find木を使って書き直し -# Union-Find木（サイズ付き） +# 20-08-12再トライ +import sys + +input = sys.stdin.readline + + -    def __init__(self, n):  # n要素で初期化　初めは全ての頂点が別々の木の根 -        self.parent = [None] * n  # 親 -        self.rank = [None] * n  # 木の深さ -        self._size = [1] * n  # 要素が属する集合の大きさ（根の要素のみ参照すること） -        for i in range(n): -            self.parent[i] = i -            self.rank[i] = 0 +    def __init__(self, n): +        self.rank = [0] * n +        self.par = list(range(n)) +        self._size = [1] * n  # 木の根のみ有効、集合に属する要素数 -    # 木の根を求める -    def root_of(self, x): -        children = [x] -        while self.parent[x] != x: -            x = self.parent[x] -            children.append(x) -        for ch in children:  # 根の子供として張りなおす -            self.parent[ch] = x +    def find(self, x): +        ch = [] +        while self.par[x] != x: +            ch.append(x) +            x = self.par[x] +        for c in ch: +            self.par[c] = x -    # xとyの属する集合を併合 -    def unite(self, x, y): -        rx = self.root_of(x) -        ry = self.root_of(y) +    def union(self, x, y): +        rx = self.find(x) +        ry = self.find(y) -        if self.rank[rx] < self.rank[ry]:  # ランクの小さい木から大きい木の根に辺を張る -            self.parent[rx] = ry  # rxをryの子とする -            self._size[ry] += self._size[rx] -        else: -            self.parent[ry] = rx +        if self.rank[rx] >= self.rank[ry]: +            self.par[ry] = rx +        else: +            self.par[rx] = ry +            self._size[ry] += self._size[rx] -    # 同じ集合に属するかどうか -    def is_same(self, x, y): -        return self.root_of(x) == self.root_of(y) +    def same(self, x, y): +        return self.find(x) == self.find(y) -    # 頂点xが属する集合のサイズ -        return self._size[self.root_of(x)] +        return self._size[self.find(x)] -# 入力 -A = [None] * M -B = [None] * M -for i in range(M): -    A[i], B[i] = [int(x) - 1 for x in input().split()] -# 島同士が全く繋がっていない状態からスタート -# M-1番目, M-2番目, ..., , 2番目, 1番目の橋の順に橋をかけていく -inconv = [-1] * (M - 1) + [N * (N - 1) // 2]  # 不便さ +E = [tuple(int(x) - 1 for x in input().split()) for _ in range(M)] +inconv = [0] * M +inconv[M - 1] = N * (N - 1) // 2 -    # i番目の橋をかける -    if not uf.is_same(A[i], B[i]): -        size_a = uf.size(A[i])  # A[i]が属する集合の大きさ -        size_b = uf.size(B[i])  # B[i]が属する集合の大きさ -        inconv[i - 1] = inconv[i] - size_a * size_b -        uf.unite(A[i], B[i]) -    else: -        inconv[i - 1] = inconv[i] +    a = E[i][0] +    b = E[i][1] +    inconv[i - 1] = inconv[i] +    if uf.same(a, b): +        continue +    inconv[i - 1] -= uf.size(a) * uf.size(b) +    uf.union(a, b)