N, M = list(map(int, input().split()))

A, B = list(zip(*(list(map(int, input().split())) for _ in range(M))))





class UFT:

    def __init__(self, n):

        self.sizes = [1] * n

        self.par = list(range(n))



    def find(self, x):

        if x == self.par[x]:

            return x

        self.par[x] = self.find(self.par[x])

        return self.par[x]



    def unite(self, x, y):

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

        if x == y:

            return

        if self.sizes[x] < self.sizes[y]:

            x, y = y, x

        self.par[y] = x

        self.sizes[x] += self.sizes[y]



    def same(self, x, y):

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



    def size(self, x):

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



u = UFT(N + 1)

ans = [0 for _ in range(M)]

z = N * (N - 1) // 2

for i in range(1, M + 1):

    ans[-i] = z

    if not u.same(A[-i], B[-i]):

        z -= u.size(A[-i]) * u.size(B[-i])

    u.unite(A[-i], B[-i])



for a in ans:

    print(a)
# 入力

N, M = list(map(int, input().split()))

A, B = (

    list(zip(*(list(map(int, input().split())) for _ in range(M)))) if M else

    ((), ())

)





class UnionFindTree:

    def __init__(self, n):

        self.p = [i for i in range(n + 1)]

        self.r = [1 for _ in range(n + 1)]



    def find(self, x):

        if self.p[x] != x:

            self.p[x] = self.find(self.p[x])

        return self.p[x]



    def union(self, x, y):

        px = self.find(x)

        py = self.find(y)

        if px != py:

            if self.r[px] < self.r[py]:

                self.p[px] = py

                self.r[py] += self.r[px]

            else:

                self.p[py] = px

                self.r[px] += self.r[py]



    def same(self, x, y):

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





# クエリを逆順に処理して不便さを求める

utf = UnionFindTree(N)

xs = []

d = N * (N - 1) // 2

for a, b in reversed(list(zip(A, B))):

    xs.append(d)

    if not utf.same(a, b):

        d -= utf.r[utf.find(a)] * utf.r[utf.find(b)]

        utf.union(a, b)

ans = '\n'.join(str(x) for x in reversed(xs))



# 出力

print(ans)

N, M = list(map(int, input().split()))
A, B = list(zip(*(list(map(int, input().split())) for _ in range(M))))


class UFT:
    def __init__(self, n):
        self.sizes = [1] * n
        self.par = list(range(n))

    def find(self, x):
        if x == self.par[x]:
            return x
        self.par[x] = self.find(self.par[x])
        return self.par[x]

    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return
        if self.sizes[x] < self.sizes[y]:
            x, y = y, x
        self.par[y] = x
        self.sizes[x] += self.sizes[y]

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

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


u = UFT(N + 1)
ans = [0 for _ in range(M)]
z = N * (N - 1) // 2
for i in range(1, M + 1):
    ans[-i] = z
    if not u.same(A[-i], B[-i]):
        z -= u.size(A[-i]) * u.size(B[-i])
    u.unite(A[-i], B[-i])
for a in ans:
    print(a)

# 入力
N, M = list(map(int, input().split()))
A, B = (
    list(zip(*(list(map(int, input().split())) for _ in range(M)))) if M else ((), ())
)


class UnionFindTree:
    def __init__(self, n):
        self.p = [i for i in range(n + 1)]
        self.r = [1 for _ in range(n + 1)]

    def find(self, x):
        if self.p[x] != x:
            self.p[x] = self.find(self.p[x])
        return self.p[x]

    def union(self, x, y):
        px = self.find(x)
        py = self.find(y)
        if px != py:
            if self.r[px] < self.r[py]:
                self.p[px] = py
                self.r[py] += self.r[px]
            else:
                self.p[py] = px
                self.r[px] += self.r[py]

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


# クエリを逆順に処理して不便さを求める
utf = UnionFindTree(N)
xs = []
d = N * (N - 1) // 2
for a, b in reversed(list(zip(A, B))):
    xs.append(d)
    if not utf.same(a, b):
        d -= utf.r[utf.find(a)] * utf.r[utf.find(b)]
        utf.union(a, b)
ans = "\n".join(str(x) for x in reversed(xs))
# 出力
print(ans)

+# 入力 -A, B = list(zip(*(list(map(int, input().split())) for _ in range(M)))) +A, B = ( +    list(zip(*(list(map(int, input().split())) for _ in range(M)))) if M else ((), ()) +) -class UFT: +class UnionFindTree: -        self.sizes = [1] * n -        self.par = list(range(n)) +        self.p = [i for i in range(n + 1)] +        self.r = [1 for _ in range(n + 1)] -        if x == self.par[x]: -            return x -        self.par[x] = self.find(self.par[x]) -        return self.par[x] +        if self.p[x] != x: +            self.p[x] = self.find(self.p[x]) +        return self.p[x] -    def unite(self, x, y): -        x, y = self.find(x), self.find(y) -        if x == y: -            return -        if self.sizes[x] < self.sizes[y]: -            x, y = y, x -        self.par[y] = x -        self.sizes[x] += self.sizes[y] +    def union(self, x, y): +        px = self.find(x) +        py = self.find(y) +        if px != py: +            if self.r[px] < self.r[py]: +                self.p[px] = py +                self.r[py] += self.r[px] +            else: +                self.p[py] = px +                self.r[px] += self.r[py] -    def size(self, x): -        return self.sizes[self.find(x)] - -u = UFT(N + 1) -ans = [0 for _ in range(M)] -z = N * (N - 1) // 2 -for i in range(1, M + 1): -    ans[-i] = z -    if not u.same(A[-i], B[-i]): -        z -= u.size(A[-i]) * u.size(B[-i]) -    u.unite(A[-i], B[-i]) -for a in ans: -    print(a) +# クエリを逆順に処理して不便さを求める +utf = UnionFindTree(N) +xs = [] +d = N * (N - 1) // 2 +for a, b in reversed(list(zip(A, B))): +    xs.append(d) +    if not utf.same(a, b): +        d -= utf.r[utf.find(a)] * utf.r[utf.find(b)] +        utf.union(a, b) +ans = "\n".join(str(x) for x in reversed(xs)) +# 出力 +print(ans)