# cnt->size
N,M = map(int,input().split())
AB = [list(map(int,input().split())) for _ in range(M)]
AB.reverse()    # 逆から考える

ans_list = [-1 for i in range(M)]
ans_list[M-1] = N*(N-1)//2

# parent(親)
par = [i for i in range(N+1)]
# rank(深さ)
rank = [0 for i in range(N+1)]
# 同グループの頂点数
size = [1 for i in range(N+1)]

# 木の根を求める
def root(x):
    if par[x] == x:             # 根の時
        return x
    else:
        par[x] = root(par[x])   # 経路圧縮
        return par[x]

# xとyの属する集合を併合(ランク有)
def unite(x,y):
    x = root(x)
    y = root(y)
    if x == y:
        return
    if rank[x] < rank[y]:
        par[x] = y
        size[y] += size[x]
    else:
        par[y] = x
        size[x] += size[y]
        if rank[x] == rank[y]:
            rank[x] += 1

for i in range(M-1):
    a,b = AB[i][0],AB[i][1]
    # 答えはans_list[M-2-i]を書き換える
    if root(a) == root(b):
        ans_list[M-2-i] = ans_list[M-1-i]
        continue
    else:
        ans_list[M-2-i] = ans_list[M-1-i] - size[root(a)]*size[root(b)]
        unite(a,b)
print('\n'.join(map(str,ans_list)))
 N,M = map(int,input().split()) N map(int,input().split()) map int input().split() ().split () input split M list(map(int,input().split())) for _ in range(M) for _ in range(M) _ range(M) range M for _ in range(M) list(map(int,input().split())) list map(int,input().split()) map int input().split() ().split () input split AB = [list(map(int,input().split())) for _ in range(M)] AB [list(map(int,input().split())) for _ in range(M)] AB.reverse() AB.reverse AB reverse -1 for i in range(M) for i in range(M) i range(M) range M for i in range(M) -1 ans_list = [-1 for i in range(M)] ans_list [-1 for i in range(M)] ans_list[M-1] = N*(N-1)//2 ans_list[M-1] ans_list M-1 M 1 N*(N-1)//2 N*(N-1) N N-1 N 1 2 i for i in range(N+1) for i in range(N+1) i range(N+1) range N+1 N 1 for i in range(N+1) i par = [i for i in range(N+1)] par [i for i in range(N+1)] 0 for i in range(N+1) for i in range(N+1) i range(N+1) range N+1 N 1 for i in range(N+1) 0 rank = [0 for i in range(N+1)] rank [0 for i in range(N+1)] 1 for i in range(N+1) for i in range(N+1) i range(N+1) range N+1 N 1 for i in range(N+1) 1 size = [1 for i in range(N+1)] size [1 for i in range(N+1)] def root(x):
    if par[x] == x:             # 根の時
        return x
    else:
        par[x] = root(par[x])   # 経路圧縮
        return par[x]

# xとyの属する集合を併合(ランク有) root if par[x] == x:             # 根の時
        return x
    else:
        par[x] = root(par[x])   # 経路圧縮
        return par[x]

# xとyの属する集合を併合(ランク有) par[x] == x par[x] par x x return x x par[x] = root(par[x]) par[x] par x root(par[x]) root par[x] par x return par[x] par[x] par x x x def unite(x,y):
    x = root(x)
    y = root(y)
    if x == y:
        return
    if rank[x] < rank[y]:
        par[x] = y
        size[y] += size[x]
    else:
        par[y] = x
        size[x] += size[y]
        if rank[x] == rank[y]:
            rank[x] += 1 unite x = root(x) x root(x) root x y = root(y) y root(y) root y if x == y:
        return
     x == y x y return if rank[x] < rank[y]:
        par[x] = y
        size[y] += size[x]
    else:
        par[y] = x
        size[x] += size[y]
        if rank[x] == rank[y]:
            rank[x] += 1 rank[x] < rank[y] rank[x] rank x rank[y] rank y par[x] = y par[x] par x y size[y] += size[x] size[y] size y size[x] size x par[y] = x par[y] par y x size[x] += size[y] size[x] size x size[y] size y if rank[x] == rank[y]:
            rank[x] += 1 rank[x] == rank[y] rank[x] rank x rank[y] rank y rank[x] += 1 rank[x] rank x 1 x x y y for i in range(M-1):
    a,b = AB[i][0],AB[i][1]
    # 答えはans_list[M-2-i]を書き換える
    if root(a) == root(b):
        ans_list[M-2-i] = ans_list[M-1-i]
        continue
    else:
        ans_list[M-2-i] = ans_list[M-1-i] - size[root(a)]*size[root(b)]
        unite(a,b) i range(M-1) range M-1 M 1 a,b = AB[i][0],AB[i][1] a AB[i][0] [i] AB i 0 b AB[i][1] [i] AB i 1 if root(a) == root(b):
        ans_list[M-2-i] = ans_list[M-1-i]
        continue
    else:
        ans_list[M-2-i] = ans_list[M-1-i] - size[root(a)]*size[root(b)]
        unite(a,b) root(a) == root(b) root(a) root a root(b) root b ans_list[M-2-i] = ans_list[M-1-i] ans_list[M-2-i] ans_list M-2-i M-2 M 2 i ans_list[M-1-i] ans_list M-1-i M-1 M 1 i continue ans_list[M-2-i] = ans_list[M-1-i] - size[root(a)]*size[root(b)] ans_list[M-2-i] ans_list M-2-i M-2 M 2 i ans_list[M-1-i] - size[root(a)]*size[root(b)] ans_list[M-1-i] ans_list M-1-i M-1 M 1 i size[root(a)]*size[root(b)] size[root(a)] size root(a) root a size[root(b)] size root(b) root b unite(a,b) unite a b print('\n'.join(map(str,ans_list))) print '\n'.join(map(str,ans_list)) '\n'.join '\n' join map(str,ans_list) map str ans_list AB = [list(map(int,input().split())) for _ in range(M)] [list(map(int,input().split())) for _ in range(M)] AB par = [i for i in range(N+1)] [i for i in range(N+1)] par a,b = AB[i][0],AB[i][1] AB[i][0] a b = AB[i][0],AB[i][1] AB[i][1] b ans_list = [-1 for i in range(M)] [-1 for i in range(M)] ans_list def root(x):
    if par[x] == x:             # 根の時
        return x
    else:
        par[x] = root(par[x])   # 経路圧縮
        return par[x]

# xとyの属する集合を併合(ランク有) def root(x):
    if par[x] == x:             # 根の時
        return x
    else:
        par[x] = root(par[x])   # 経路圧縮
        return par[x]

# xとyの属する集合を併合(ランク有) root rank = [0 for i in range(N+1)] [0 for i in range(N+1)] rank size = [1 for i in range(N+1)] [1 for i in range(N+1)] size M = map(int,input().split()) map(int,input().split()) M N,M = map(int,input().split()) map(int,input().split()) N def unite(x,y):
    x = root(x)
    y = root(y)
    if x == y:
        return
    if rank[x] < rank[y]:
        par[x] = y
        size[y] += size[x]
    else:
        par[y] = x
        size[x] += size[y]
        if rank[x] == rank[y]:
            rank[x] += 1 def unite(x,y):
    x = root(x)
    y = root(y)
    if x == y:
        return
    if rank[x] < rank[y]:
        par[x] = y
        size[y] += size[x]
    else:
        par[y] = x
        size[x] += size[y]
        if rank[x] == rank[y]:
            rank[x] += 1 unite
# cnt->size
N,M = map(int,input().split())
AB = [list(map(int,input().split())) for _ in range(M)]
AB.reverse()    # 逆から考える

ans_list = [-1 for i in range(M)]
ans_list[M-1] = N*(N-1)//2

# parent(親)
par = [i for i in range(N+1)]
# rank(深さ)
rank = [0 for i in range(N+1)]
# 同グループの頂点数
size = [1 for i in range(N+1)]

# 木の根を求める
def root(x):
    if par[x] == x:             # 根の時
        return x
    else:
        par[x] = root(par[x])   # 経路圧縮
        return par[x]

# xとyの属する集合を併合(ランク有)
def unite(x,y):
    x = root(x)
    y = root(y)
    if x == y:
        return
    if rank[x] < rank[y]:
        par[x] = y
        size[y] += size[x]
    else:
        par[y] = x
        size[x] += size[y]
        if rank[x] == rank[y]:
            rank[x] += 1

for i in range(M-1):
    a,b = AB[i][0],AB[i][1]
    # 答えはans_list[M-2-i]を書き換える
    if root(a) == root(b):
        ans_list[M-2-i] = ans_list[M-1-i]
        continue
    else:
        ans_list[M-2-i] = ans_list[M-1-i] - size[root(a)]*size[root(b)]
        unite(a,b)
print('\n'.join(map(str,ans_list)))

