#!/usr/bin/env python3

from pprint import pprint
import sys

sys.setrecursionlimit(10 ** 6)
INF = float('inf')


N, M = map(int, input().split())
edges = []
for _ in range(M):
    u, v = map(int, input().split())
    edges.append([u-1, v-1])

# どの島も繋がっていないとき、不便さは最大値 N * (N-1) / 2 を取る
# 1 本ずつ減らすのではなく、最悪のケースから順に辺を追加していくことを考える
# ある辺 u <-> v を追加したときに、島の集合 a と島の集合 b が連結になったとすると、
# 不便さは size(a) * size(b) だけ減る
# disjoint set として島を管理し、最悪のケースから各辺を追加したときの不便さを計算すればよい


def has_same_root(u, v):
    return root(u) == root(v)


def root(u):
    if parents[u] < 0:
        return u
    parents[u] = root(parents[u])
    return parents[u]


def unite(u, v):
    # print(f'unite {u}, {v}')
    u_root = root(u)
    v_root = root(v)
    # pprint(parents)
    # print(f'u_root = {u_root}, v_root = {v_root}')
    # print(f'size(u_root) = {size(u_root)}, size(v_root) = {size(v_root)}')
    if size(u_root) > size(v_root):
        u_root, v_root = v_root, u_root
    parents[u_root] -= size(v_root)
    parents[v_root] = u_root
    # pprint(parents)


def size(u):
    return -parents[root(u)]


parents = [-1 for _ in range(N)]
inconvenience = N * (N-1) // 2
ans = [inconvenience]

for u, v in reversed(edges):
    # print(f'\nu = {u}, v = {v}')
    if not has_same_root(u, v):
        inconvenience -= size(u) * size(v)
        unite(u, v)
    ans.append(inconvenience)

for i in reversed(range(M)):
    print(ans[i]) from pprint import pprint import sys sys sys.setrecursionlimit(10 ** 6) sys.setrecursionlimit sys setrecursionlimit 10 ** 6 10 6 INF = float('inf') INF float('inf') float 'inf' N, M = map(int, input().split()) N map(int, input().split()) map int input().split() ().split () input split M edges = [] edges [] for _ in range(M):
    u, v = map(int, input().split())
    edges.append([u-1, v-1])

# どの島も繋がっていないとき、不便さは最大値 N * (N-1) / 2 を取る
# 1 本ずつ減らすのではなく、最悪のケースから順に辺を追加していくことを考える
# ある辺 u <-> v を追加したときに、島の集合 a と島の集合 b が連結になったとすると、
# 不便さは size(a) * size(b) だけ減る
# disjoint set として島を管理し、最悪のケースから各辺を追加したときの不便さを計算すればよい _ range(M) range M u, v = map(int, input().split()) u map(int, input().split()) map int input().split() ().split () input split v edges.append([u-1, v-1]) edges.append edges append [u-1, v-1] u-1 u 1 v-1 v 1 def has_same_root(u, v):
    return root(u) == root(v) has_same_root return root(u) == root(v) root(u) == root(v) root(u) root u root(v) root v u u v v def root(u):
    if parents[u] < 0:
        return u
    parents[u] = root(parents[u])
    return parents[u] root if parents[u] < 0:
        return u
     parents[u] < 0 parents[u] parents u 0 return u u parents[u] = root(parents[u]) parents[u] parents u root(parents[u]) root parents[u] parents u return parents[u] parents[u] parents u u u def unite(u, v):
    # print(f'unite {u}, {v}')
    u_root = root(u)
    v_root = root(v)
    # pprint(parents)
    # print(f'u_root = {u_root}, v_root = {v_root}')
    # print(f'size(u_root) = {size(u_root)}, size(v_root) = {size(v_root)}')
    if size(u_root) > size(v_root):
        u_root, v_root = v_root, u_root
    parents[u_root] -= size(v_root)
    parents[v_root] = u_root
    # pprint(parents) unite u_root = root(u) u_root root(u) root u v_root = root(v) v_root root(v) root v if size(u_root) > size(v_root):
        u_root, v_root = v_root, u_root
     size(u_root) > size(v_root) size(u_root) size u_root size(v_root) size v_root u_root, v_root = v_root, u_root u_root v_root v_root u_root parents[u_root] -= size(v_root) parents[u_root] parents u_root size(v_root) size v_root parents[v_root] = u_root parents[v_root] parents v_root u_root u u v v def size(u):
    return -parents[root(u)] size return -parents[root(u)] -parents[root(u)] parents[root(u)] parents root(u) root u u u -1 for _ in range(N) for _ in range(N) _ range(N) range N for _ in range(N) -1 parents = [-1 for _ in range(N)] parents [-1 for _ in range(N)] inconvenience = N * (N-1) // 2 inconvenience N * (N-1) // 2 N * (N-1) N N-1 N 1 2 ans = [inconvenience] ans [inconvenience] inconvenience for u, v in reversed(edges):
    # print(f'\nu = {u}, v = {v}')
    if not has_same_root(u, v):
        inconvenience -= size(u) * size(v)
        unite(u, v)
    ans.append(inconvenience) u v reversed(edges) reversed edges if not has_same_root(u, v):
        inconvenience -= size(u) * size(v)
        unite(u, v)
     not has_same_root(u, v) has_same_root(u, v) has_same_root u v inconvenience -= size(u) * size(v) inconvenience size(u) * size(v) size(u) size u size(v) size v unite(u, v) unite u v ans.append(inconvenience) ans.append ans append inconvenience for i in reversed(range(M)):
    print(ans[i]) i reversed(range(M)) reversed range(M) range M print(ans[i]) print ans[i] ans i def size(u):
    return -parents[root(u)] def size(u):
    return -parents[root(u)] size v = map(int, input().split()) map(int, input().split()) v INF = float('inf') float('inf') INF edges = [] [] edges M = map(int, input().split()) map(int, input().split()) M inconvenience = N * (N-1) // 2 N * (N-1) // 2 inconvenience def root(u):
    if parents[u] < 0:
        return u
    parents[u] = root(parents[u])
    return parents[u] def root(u):
    if parents[u] < 0:
        return u
    parents[u] = root(parents[u])
    return parents[u] root def has_same_root(u, v):
    return root(u) == root(v) def has_same_root(u, v):
    return root(u) == root(v) has_same_root u, v = map(int, input().split()) map(int, input().split()) u N, M = map(int, input().split()) map(int, input().split()) N inconvenience -= size(u) * size(v) size(u) * size(v) inconvenience def unite(u, v):
    # print(f'unite {u}, {v}')
    u_root = root(u)
    v_root = root(v)
    # pprint(parents)
    # print(f'u_root = {u_root}, v_root = {v_root}')
    # print(f'size(u_root) = {size(u_root)}, size(v_root) = {size(v_root)}')
    if size(u_root) > size(v_root):
        u_root, v_root = v_root, u_root
    parents[u_root] -= size(v_root)
    parents[v_root] = u_root
    # pprint(parents) def unite(u, v):
    # print(f'unite {u}, {v}')
    u_root = root(u)
    v_root = root(v)
    # pprint(parents)
    # print(f'u_root = {u_root}, v_root = {v_root}')
    # print(f'size(u_root) = {size(u_root)}, size(v_root) = {size(v_root)}')
    if size(u_root) > size(v_root):
        u_root, v_root = v_root, u_root
    parents[u_root] -= size(v_root)
    parents[v_root] = u_root
    # pprint(parents) unite ans = [inconvenience] [inconvenience] ans parents = [-1 for _ in range(N)] [-1 for _ in range(N)] parents
#!/usr/bin/env python3

from pprint import pprint
import sys

sys.setrecursionlimit(10 ** 6)
INF = float('inf')


N, M = map(int, input().split())
edges = []
for _ in range(M):
    u, v = map(int, input().split())
    edges.append([u-1, v-1])

# どの島も繋がっていないとき、不便さは最大値 N * (N-1) / 2 を取る
# 1 本ずつ減らすのではなく、最悪のケースから順に辺を追加していくことを考える
# ある辺 u <-> v を追加したときに、島の集合 a と島の集合 b が連結になったとすると、
# 不便さは size(a) * size(b) だけ減る
# disjoint set として島を管理し、最悪のケースから各辺を追加したときの不便さを計算すればよい


def has_same_root(u, v):
    return root(u) == root(v)


def root(u):
    if parents[u] < 0:
        return u
    parents[u] = root(parents[u])
    return parents[u]


def unite(u, v):
    # print(f'unite {u}, {v}')
    u_root = root(u)
    v_root = root(v)
    # pprint(parents)
    # print(f'u_root = {u_root}, v_root = {v_root}')
    # print(f'size(u_root) = {size(u_root)}, size(v_root) = {size(v_root)}')
    if size(u_root) > size(v_root):
        u_root, v_root = v_root, u_root
    parents[u_root] -= size(v_root)
    parents[v_root] = u_root
    # pprint(parents)


def size(u):
    return -parents[root(u)]


parents = [-1 for _ in range(N)]
inconvenience = N * (N-1) // 2
ans = [inconvenience]

for u, v in reversed(edges):
    # print(f'\nu = {u}, v = {v}')
    if not has_same_root(u, v):
        inconvenience -= size(u) * size(v)
        unite(u, v)
    ans.append(inconvenience)

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