CodeEff/ECCO huggingface dataset:
# 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)
    y = self.find(y)
    if x == y:
      return
    if self.parents[x] > self.parents[y]:
      x, y = y, x
    self.parents[x] += self.parents[y]
    self.parents[y] = x

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

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

  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, x in enumerate(self.parents) if x < 0]

  def group_count(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 = map(int, input().split())
AB = []
for _ in range(M):
  A, B = map(int, input().split())
  AB.append((A-1, B-1))

uf = UnionFind(N)
unhappy = [N*(N-1)//2]

for A, B in reversed(AB):
  uf.union(A, B)
  happy = 0
  for i in uf.roots():
    temp = uf.size(i)
    happy += temp*(temp-1)//2
  unhappy.append(N*(N-1)//2 - happy)

print(*reversed(unhappy[:-1]), sep="\n")


# 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 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
    self.parents[x] += self.parents[y]
    self.parents[y] = x

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

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

  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, x in enumerate(self.parents) if x < 0]

  def group_count(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 = map(int, input().split())
AB = []
for _ in range(M):
  A, B = map(int, input().split())
  AB.append((A-1, B-1))

uf = UnionFind(N)
unhappy = [N*(N-1)//2]

def conb(x):
  return x*(x-1)//2

for A, B in reversed(AB):
  old_ap, old_bp = uf.find(A), uf.find(B)
  if old_ap == old_bp:
    uf.union(A, B)
    unhappy.append(unhappy[-1])
  else:
    old_happy = conb(uf.size(old_ap)) + conb(uf.size(old_bp))
    uf.union(A, B)
    new_happy = conb(uf.size(A))
    happy = new_happy - old_happy
    unhappy.append(unhappy[-1] - happy)

print(*reversed(unhappy[:-1]), sep="\n")
# Original solution
class UnionFind():
  def __init__(self, n):
    self.n=n
    self.p=[-1]*n

  def find(self,x):
    if self.p[x]<0:
      return x
    else:
      self.p[x]=self.find(self.p[x])
    return self.p[x]

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

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

    if self.p[x]>self.p[y]:
      x,y=y,x

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

  def members(self,x):
    p = self.find(x)
    return [i for i in range(self.n) if self.find(i)==p]

  def roots(self):
    return [i for i,x in enumerate(self.p) if x<0]

  def gcount(self):
    return len(self.roots())
 
  def uprint(self):
    print((self.p))
    return

n,m=list(map(int,input().split()))
b=[[int(x) for x in input().split()] for y in range(m)]
u=n*(n-1)//2

s=[]
a=[u]
uf=UnionFind(n)

for i in range(m-1,0,-1):
  uf.unite(b[i][0]-1,b[i][1]-1)
  t = 0
  for j in uf.roots():
    n = len(uf.members(j))
    t += (n * (n-1)) // 2
  a.append(u-t)

a.reverse()
for i in range(len(a)):
  print((a[i]))


# Optimized solution
n, m = list(map(int, input().split()))
e = [[int(x) for x in input().split()] for _ in range(m)]

u = [-1]*(n+1)

def find(x):
  return x if u[x] < 0 else find(u[x])

t = n*(n-1)// 2
s = [t]

for i in range(m-1,0,-1):
  a = find(e[i][0])
  b = find(e[i][1])
  if a > b:
    a, b = b, a
  if a != b:
    t -= u[a]*u[b]
    u[a] += u[b]
    u[b] = a
  s.append(t)

for i in reversed(s):
  print(i)
# Original solution
n,m = list(map(int,input().split()))
isl1,isl2 = [0]*m,[0]*m
for i in range(m):
    (isl1[i], isl2[i]) = list(map(int,input().split()))
    isl1[i] -= 1
    isl2[i] -= 1
boss = [-1]*n
member_number = [1]*n
dpt = [0]*n

ans = [0]*m
s = (n*(n-1))//2
ans[m-1] = s
 
def search_member(island, boss):
     m = 0
     while boss[island] >= 0:
          island = boss[island]
          m += 1
     return island,m
 
for j in range(m-1):
     i = m-j-1
     island1,island2 = isl1[i],isl2[i]
     parent1,m1 = search_member(island1, boss)
     parent2,m2 = search_member(island2, boss)
     if parent1 != parent2:
          if dpt[m1] < dpt[m2]:
               (parent1,parent2) = (parent2,parent1)
          boss[parent2] = parent1
          s -= member_number[parent1]*member_number[parent2]
          member_number[parent1] += member_number[parent2]
          member_number[parent2] = 0
          dpt[parent1] = max(dpt[parent1],dpt[parent2]+1)
     ans[i-1] = s
         
for i in range(m):
     print((ans[i]))

# Optimized solution
#https://atcoder.jp/contests/abc120/submissions/4458925
(N,M) = list(map(int,input().split()))
A = [0]*M
B = [0]*M
for i in range(M):
    (A[i], B[i]) = list(map(int,input().split()))
    A[i] -= 1
    B[i] -= 1
 
parent = [-1]*N
depth = [0] * N
 
def boss(n):
    d = 0
    while parent[n] >= 0:
        n = parent[n]
        d += 1
    return n,d
 
P = [1]*N
S = (N*(N-1))//2
 
ans = [0] * M
ans[M-1] = S
 
for i in range(M-1):
    j = M-1-i
    bA, dA = boss(A[j])
    bB, dB = boss(B[j])
    if bA != bB:
        if depth[bA] < depth[bB]:
            (bA, bB) = (bB, bA)
        parent[bB] = bA
        S -= P[bA]*P[bB]
        P[bA] = P[bA] + P[bB]
        P[bB] = 0
        depth[bA] = max(depth[bA],depth[bB]+1)
    ans[j-1] = S
 
for i in range(M):
    print((ans[i]))
# Original solution
import sys,queue,math
sys.setrecursionlimit(10**7)
input = sys.stdin.readline
INF = 10**18
MOD = 10**9 + 7
LI = lambda : [int(x) for x in input().split()]
_LI = lambda : [int(x)-1 for x in input().split()]

N,M = LI()
B = [_LI() for _ in range(M)]

g = [i for i in range(N)]
c = [1 for _ in range(N)]

def root(x):
    if x != g[x]: g[x] = root(g[x])
    return g[x]

def union(x,y):
    rx = root(x)
    ry = root(y)
    if rx != ry:
        g[ry] = rx
        c[rx] += c[ry]
        c[ry] = 0

ans = []
B.reverse()
for a,b in B:
    ra = root(a)
    rb = root(b)
    if ra == rb:
        ans.append(0)
    else:
        ans.append(c[ra]*c[rb])
        union(ra,rb)

ans.reverse()
x = 0
for a in ans:
    x += a
    print (x)

# Optimized solution
import sys,queue,math
sys.setrecursionlimit(10**7)
input = sys.stdin.readline
INF = 10**18
MOD = 10**9 + 7
LI = lambda : [int(x) for x in input().split()]
_LI = lambda : [int(x)-1 for x in input().split()]

N,M = LI()
B = [_LI() for _ in range(M)]

g = [i for i in range(N)]
c = [1 for _ in range(N)]

def root(x):
    if x != g[x]: g[x] = root(g[x])
    return g[x]

def union(x,y):
    rx = root(x)
    ry = root(y)
    if rx != ry:
        if c[ry] > c[rx]: ry,rx = rx,ry
        g[ry] = rx
        c[rx] += c[ry]
        c[ry] = 0

ans = []
B.reverse()
for a,b in B:
    ra = root(a)
    rb = root(b)
    if ra == rb:
        ans.append(0)
    else:
        ans.append(c[ra]*c[rb])
        union(ra,rb)

ans.reverse()
x = 0
for a in ans:
    x += a
    print (x)
# Original solution
#!/usr/bin/env python3

from pprint import pprint
import sys

sys.setrecursionlimit(10 ** 6)


# 辺を取り除くのではなく、辺が無い状態から始めて辺を順にグラフに追加していくことを考える
# 最初は辺が無いので不便さは N * (N-1) / 2
# 辺 u <-> v を追加したとき、頂点 u, v が既に到達可能であるなら、不便さは変わらない
# そうでなければ、不便さは直前の値より size[u] * size[v] だけ小さくなる

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


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


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


# unite by size
def unite(u, v):
    u_root = root(u)
    v_root = root(v)
    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


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


# the parent node of a root node has the size of tree (negative value)
parents = [-1 for v in range(N)]

ans = []
current = N * (N-1) // 2
for i in range(M):
    u, v = edges[M-1-i]
    # print(f'current = {current}')
    # print(f'u = {u}, v = {v}')
    # print(f'parents = {parents}')
    ans.append(current)
    if has_same_root(u, v):
        # print('skip')
        continue
    # print(f'size(u) = {size(u)}, size(v) = {size(v)}')
    current -= size(u) * size(v)
    unite(u, v)
    # print(f'parents = {parents}\n')

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


# Optimized solution
#!/usr/bin/env python3

from pprint import pprint
import sys

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


N, M = list(map(int, input().split()))
edges = []
for _ in range(M):
    u, v = list(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(list(range(M))):
    print((ans[i]))
# Original solution
N, M = list(map(int, input().split()))
ab = [tuple([int(x)-1 for x in input().split()]) for _ in range(M)]
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n+1)]
        self.rank = [0] * (n+1) # 木の高さ
        self.n = [1] * (n+1)    # グループメンバー数
        
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]
    
    def find_n(self, x):
        return self.n[self.find(x)]
    
    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
            self.n[y] = self.n[x] + self.n[y]
        else:
            self.par[y] = x
            self.n[x] = self.n[x] + self.n[y]
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
    
    def is_same(self, x, y):
        return self.find(x) == self.find(y) 
def main():
    uf = UnionFind(N)
    p = N * (N - 1) // 2
    ans = [p]
    for x, y in reversed(ab):
        px = uf.find(x)
        py = uf.find(y)
        if px != py:
            p -= uf.find_n(px) * uf.find_n(py)
            uf.unite(px, py)
        ans.append(p)
 
    for a in reversed(ans[:-1]):
        print(a)
 
 
main()


# Optimized solution
N, M = list(map(int, input().split()))
ab = [tuple([int(x)-1 for x in input().split()]) for _ in range(M)]
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n+1)]
        self.rank = [0] * (n+1) # 木の高さ
        self.n = [1] * (n+1)    # グループメンバー数
        
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]
    
    def find_n(self, x):
        return self.n[self.find(x)]
    
    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
            self.n[y] = self.n[x] + self.n[y]
        else:
            self.par[y] = x
            self.n[x] = self.n[x] + self.n[y]
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
    
    def is_same(self, x, y):
        return self.find(x) == self.find(y) 
def main():
    uf = UnionFind(N)
    p = N * (N - 1) // 2
    ans = [p]
    for x, y in reversed(ab):
        px = uf.find(x)
        py = uf.find(y)
        if px != py:
            #p -= uf.find_n(px) * uf.find_n(py)
            p -= uf.n[px] * uf.n[py]
            uf.unite(px, py)
        ans.append(p)
 
    for a in reversed(ans[:-1]):
        print(a)
 
 
main()
# Original solution
class UnionFind():
    def __init__(self, n):
        self.parents = [-1] * n

    def find(self, x):
        tb = []
        while True:
            if self.parents[x] < 0:
                for i in tb:
                    self.parents[i] = x
                return x
            else:
                tb.append(x)
                x = self.parents[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

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

import sys
input = sys.stdin.readline
n, m = list(map(int, input().split()))
ab = [list(map(int, input().split())) for _ in range(m)]
ab.reverse()
ans = []
nC2 = n * (n - 1) // 2

uf = UnionFind(n)
for a, b in ab:
    c = nC2
    for v in uf.parents:
        if v < -1:
            c -= v * (v + 1) // 2
    ans.append(c)
    uf.union(a-1, b-1)

ans.reverse()

for ai in ans:
    print(ai)


# Optimized solution
def xC2(x):
    if x == 1:
        return 0
    else:
        return x * (x-1) // 2

class UnionFind():
    def __init__(self, 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)
        y = self.find(y)

        if x == y:
            return 0

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        nx, ny = - self.parents[x],  - self.parents[y]

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

        return xC2(nx + ny) - xC2(nx) - xC2(ny)

import sys
input = sys.stdin.readline
n, m = list(map(int, input().split()))
ab = [list(map(int, input().split())) for _ in range(m)]
ab.reverse()
ans = [xC2(n)]

uf = UnionFind(n)
for a, b in ab:
    ans.append(ans[-1] - uf.union(a-1, b-1))

ans.reverse()

for ai in ans[1:]:
    print(ai)
# Original solution
import sys
sys.setrecursionlimit(10**9)
INF=10**18
MOD=10**9+7
def input():
    return sys.stdin.readline().rstrip()

def main():
    class UnionFind():
        def __init__(self,n):
            self.par=[i for i in range(n)]
            self.siz=[1]*n
            
        def root(self,x):
            while self.par[x]!=x:
                x=self.par[x]
            return x
        
        def unite(self,x,y):
            x=self.root(x)
            y=self.root(y)
            if x==y:
                return False
            if self.siz[x]<self.siz[y]:
                x,y=y,x
            self.siz[x]+=self.siz[y]
            self.par[y]=x
            return True
        
        def is_same(self,x,y):
            return self.root(x)==self.root(y)
        
        def size(self,x):
            return self.siz[self.root(x)]
    
    N,M=list(map(int,input().split()))
    Q=[]
    for _ in range(M):
        Q.append(tuple([int(x)-1 for x in input().split()]))
    uf=UnionFind(N)
    l_ans=[]
    ans=N*(N-1)//2
    for _ in range(M):
        l_ans.append(ans)
        a,b=Q.pop()
        siz_a,siz_b=uf.size(a),uf.size(b)
        if uf.unite(a,b):
            ans-=siz_a*siz_b
    for _ in range(M):
        print((l_ans.pop()))
        
    
    

if __name__ == '__main__':
    main()


# Optimized solution
import sys
sys.setrecursionlimit(10**9)
INF=10**18
MOD=10**9+7
def input():
    return sys.stdin.readline().rstrip()

def main():
    class UnionFind():
        def __init__(self,n):
            self.par=[i for i in range(n)]
            self.siz=[1]*n
            
        def root(self,x):
            while self.par[x]!=x:
                self.par[x]=self.par[self.par[x]]
                x=self.par[x]
            return x
        
        def unite(self,x,y):
            x=self.root(x)
            y=self.root(y)
            if x==y:
                return False
            if self.siz[x]<self.siz[y]:
                x,y=y,x
            self.siz[x]+=self.siz[y]
            self.par[y]=x
            return True
        
        def is_same(self,x,y):
            return self.root(x)==self.root(y)
        
        def size(self,x):
            return self.siz[self.root(x)]
    
    N,M=list(map(int,input().split()))
    Q=[]
    for _ in range(M):
        Q.append(tuple([int(x)-1 for x in input().split()]))
    uf=UnionFind(N)
    l_ans=[]
    ans=N*(N-1)//2
    for _ in range(M):
        l_ans.append(ans)
        a,b=Q.pop()
        siz_a,siz_b=uf.size(a),uf.size(b)
        if uf.unite(a,b):
            ans-=siz_a*siz_b
    for _ in range(M):
        print((l_ans.pop()))
        
    
    

if __name__ == '__main__':
    main()
# Original solution
N, M = list(map(int, input().split()))
lis = [[x, -1] for x in range(1, N + 1)]
Blis = [list(map(int, input().split())) for _ in range(M)]
inc = int(N*(N - 1)/2)
ans = [x for x in range(M)]
ans[M - 1] = inc
def root(a):
    if lis[a - 1][1] < 0:
        return lis[a - 1][0]
    else:
        k = root(lis[a - 1][1])
        lis[a - 1][1] = k
        return k
def size(a):
    return -lis[root(a) - 1][1]
def connect(a, b):
    A = root(a)
    B = root(b)
    if A == B:
        return None
    else:
        if size(A) < size(B):
            A, B = B, A
        lis[A - 1][1] += lis[B - 1][1]
        lis[B - 1][1] = A
for i in reversed(list(range(0, M))):
    if root(Blis[i][0]) != root(Blis[i][1]):
        ans[i - 1] = ans[i] - size(Blis[i][0])*size(Blis[i][1])
    else:
      ans[i - 1] = ans[i]
    connect(Blis[i][0], Blis[i][1])
ans[M - 1] = inc    
for i in range(M):
  print((ans[i]))

# Optimized solution
N, M = list(map(int, input().split()))
lis = [[x, -1] for x in range(1, N + 1)]
Blis = [list(map(int, input().split())) for _ in range(M)]
inc = int(N*(N - 1)/2)
ans = [x for x in range(M)]
ans[M - 1] = inc
def root(a):
    if lis[a - 1][1] < 0:
        return lis[a - 1][0]
    else:
        k = root(lis[a - 1][1])
        lis[a - 1][1] = k
        return k
def size(a):
    return -lis[root(a) - 1][1]
def connect(a, b):
    A = root(a)
    B = root(b)
    if A == B:
        return None
    else:
        if size(A) < size(B):
            A, B = B, A
        lis[A - 1][1] += lis[B - 1][1]
        lis[B - 1][1] = A
for i in reversed(list(range(1, M))):
    if root(Blis[i][0]) != root(Blis[i][1]):
        ans[i - 1] = ans[i] - size(Blis[i][0])*size(Blis[i][1])
        connect(Blis[i][0], Blis[i][1])
    else:
      ans[i - 1] = ans[i]    
for i in range(M):
  print((ans[i]))
# Original solution
N, M = list(map(int, input().split()))
lis = [[x, -1] for x in range(1, N + 1)]
Blis = [list(map(int, input().split())) for _ in range(M)]
inc = int(N*(N - 1)/2)
ans = [x for x in range(M)]
ans[M - 1] = inc
def root(a):
    if lis[a - 1][1] < 0:
        return lis[a - 1][0]
    else:
        k = root(lis[a - 1][1])
        lis[a - 1][1] = k
        return k
def size(a):
    return -lis[root(a) - 1][1]
def connect(a, b):
    A = root(a)
    B = root(b)
    if A == B:
        return None
    else:
        if size(A) < size(B):
            A, B = B, A
        lis[A - 1][1] += lis[B - 1][1]
        lis[B - 1][1] = A
for i in reversed(list(range(1, M))):
    if root(Blis[i][0]) != root(Blis[i][1]):
        ans[i - 1] = ans[i] - size(Blis[i][0])*size(Blis[i][1])
        connect(Blis[i][0], Blis[i][1])
    else:
      ans[i - 1] = ans[i]    
for i in range(M):
  print((ans[i]))

# Optimized solution
N, M = list(map(int, input().split()))
Parent = [-1 for x in range(N + 5)]
lis = [list(map(int, input().split())) for _ in range(M)]
ini = int(N*(N - 1)/2)
ans = [x for x in range(M)]
ans[M - 1] = ini
def root(a):
    if Parent[a] < 0:
        return a
    else:
        k = root(Parent[a])
        Parent[a] = k
        return k
def size(a):
    return -Parent[root(a)]
def connect(a, b):
    A = root(a)
    B = root(b)
    if A == B:
        return None
    else:
        if size(A) < size(B):
            A, B = B, A
        Parent[A] += Parent[B]
        Parent[B] = A
for i in reversed(list(range(1, M))):
    ans[i - 1] = ans[i]
    if root(lis[i][0]) != root(lis[i][1]):
        ans[i - 1] -= size(lis[i][0])*size(lis[i][1])
        connect(lis[i][0], lis[i][1])    
for i in range(M):
  print((ans[i]))
# Original solution
N, M = list(map(int, input().split()))
AB = [list(map(int, input().split())) for i in range(M)]
AB.reverse()
island = [[i+1] for i in range(N)]
ans = []
for m in range(M):
    count = 0
    for i in range(len(island)):
        for j in range(i+1, len(island)):
            count += len(island[i]) * len(island[j])
    ans.append(count)

    A, B = AB.pop(0)
    idxs = [None, None] # A, B
    for idx in range(len(island)):
        if A in island[idx]:
            idxs[0] = idx
        if B in island[idx]:
            idxs[1] = idx
        if None not in idxs:
            break
    if idxs[0] != idxs[1]:
        island[idxs[0]].extend(island[idxs[1]])
        del island[idxs[1]]

ans.reverse()
[print(ans[i]) for i in range(M)]


# Optimized solution
def find(idx):
    global tree
    while True:
        if tree[idx].root == True:
            return tree[idx].prev, tree[idx].size
        else:
            idx = tree[idx].prev

class Union_Find:
    def __init__(self, prev):
        self.root = True
        self.size = 1
        self.prev = prev

N, M = list(map(int, input().split()))
AB = [list(map(int, input().split())) for i in range(M)]
AB.reverse()
ans = [(N*(N-1))//2]
tree = {i:Union_Find(i) for i in range(1, N+1)}

for A, B in AB[:-1]:
    root_A, size_A = find(A)
    root_B, size_B = find(B)

    if root_A == root_B:
        ans.append(ans[-1])
    else:
        if size_A > size_B:
            x, y = root_B, root_A
        else:
            x, y = root_A, root_B

        tree[x].root = False
        tree[x].prev = y
        tree[y].size += tree[x].size

        ans.append(ans[-1] - size_A * size_B)

[print(max(0, i)) for i in ans[::-1]]