CodeEff/ECCO huggingface dataset:
# Original solution
def find(tab, a):
    if tab[a]==-1:
        return a
    tab[a] = find(tab, tab[a])
    return tab[a]

def union(tab, a, b):
    p1, p2 = find(tab, a), find(tab, b)
    if p1 != p2:
        tab[p1] = p2

def count(tab, a):
    ans = 0
    parent = find(tab, a)
    for b in range(len(tab)):
        if find(tab, b) == parent:
            ans += 1
    return ans

N, M = [int(a) for a in input().split(" ")]
ABs = [[int(a) for a in input().split(" ")] for i in range(M)]
tab = [-1]*N
arr = []

for a, b in reversed(ABs):
    pa, pb = (find(tab, a-1), find(tab, b-1))
    if pa!=pb:
        na = count(tab, pa)
        nb = count(tab, pb)
        dn = ((na+nb)*(na+nb-1)//2)-(na*(na-1)//2)-(nb*(nb-1)//2)
        arr.append(dn)
    else:
        arr.append(0)
    union(tab, a-1, b-1)

acc = 0
for cp in reversed(arr):
    acc += cp
    print(acc)


# Optimized solution
import sys
sys.setrecursionlimit(100000)

def find(tab, a):
    if tab[0][a]==a:
        return a
    tab[0][a] = find(tab, tab[0][a])
    return tab[0][a]

def union(tab, a, b):
    p1, p2 = (find(tab, a), find(tab, b))
    if p1 != p2:
        tab[0][p1] = p2
        tab[1][p2] += tab[1][p1]

def size(tab, a):
    return tab[1][a]

N, M = [int(a) for a in input().split(" ")]
ABs = [[int(a) for a in input().split(" ")] for i in range(M)]
tab = [[i for i in range(N)], [1 for i in range(N)]]
arr = []

for a, b in reversed(ABs):
        a, b = (a-1, b-1)
        pa, pb = (find(tab, a), find(tab, b))
        na, nb = (size(tab, pa), size(tab, pb))
        if pa!=pb:
            dn = ((na+nb)*(na+nb-1)//2)-(na*(na-1)//2)-(nb*(nb-1)//2)
            arr.append(dn)
            union(tab, a, b)
        else:
            arr.append(0)

acc = 0
for cp in reversed(arr):
    acc += cp
    print(acc)
# Original solution
#sizeありversion
class DisjointSet:
    def __init__(self):
        self.rank = {}
        self.p = {}
        self._size = {}

    def makeSet(self, x):
        self.p[x] = x
        self.rank[x] = 0
        self._size[x] = 1

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

    def unite(self, x, y):
        self.link(self.findSet(x), self.findSet(y))

    def link(self, x, y):
        if(self.rank[x] > self.rank[y]):
            self.p[y] = x
            self._size[x] += self._size[y]
            self._size[y] = 0
        else:
            self.p[x] = y
            self._size[y] += self._size[x]
            self._size[x] = 0
            if(self.rank[x] == self.rank[y]):
                self.rank[y] += 1

    #頂点xが属するグループと同じグループに属する頂点数を得る
    def size(self, x):
        return self._size[self.findSet(x)]

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


N, M = list(map(int, input().split()))
l = [[int(i) for i in input().split()] for i in range(M)]

ds = DisjointSet()
for i in range(N):
    ds.makeSet(i+1)

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

for i in range(M-1, 0, -1):
    a, b = l[i]
    if ds.same(a, b):
        ans[i-1] = ans[i]
    else:
        x = ds.size(a)
        y = ds.size(b)
        ans[i-1] = ans[i] - x * y
        ds.unite(a, b)

for a in ans:
    print(a)

# Optimized solution
#sizeありversion
class DisjointSet:
    def __init__(self):
        self.rank = {}
        self.p = {}
        self._size = {}

    def makeSet(self, x):
        self.p[x] = x
        self.rank[x] = 0
        self._size[x] = 1

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

    def unite(self, x, y):
        self.link(self.findSet(x), self.findSet(y))

    def link(self, x, y):
        if(self.rank[x] > self.rank[y]):
            self.p[y] = x
            self._size[x] += self._size[y]
            ##self._size[y] = 0
        else:
            self.p[x] = y
            self._size[y] += self._size[x]
            #self._size[x] = 0
            if(self.rank[x] == self.rank[y]):
                self.rank[y] += 1

    #頂点xが属するグループと同じグループに属する頂点数を得る
    def size(self, x):
        return self._size[self.findSet(x)]

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


N, M = list(map(int, input().split()))
l = [[int(i) for i in input().split()] for i in range(M)]

ds = DisjointSet()
for i in range(N):
    ds.makeSet(i+1)

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

for i in range(M-1, 0, -1):
    a, b = l[i]
    if ds.same(a, b):
        ans[i-1] = ans[i]
    else:
        x = ds.size(a)
        y = ds.size(b)
        ans[i-1] = ans[i] - x * y
        ds.unite(a, b)

for a in ans:
    print(a)
# Original solution
class Union:

  def __init__(self, num):
    self.T = [-1 for i in range(num)]

  def root(self, x):
    if self.T[x] < 0: return x
    return self.root(self.T[x])

  def size(self, x):
    return -self.T[self.root(x)]

  def merge(self, x, y):
    a = self.root(x)
    b = self.root(y)
    if a == b: return False
    if self.size(a) < self.size(b): a, b = b, a
    self.T[a] += self.T[b]
    self.T[b] = a
    return True

N, M = list(map(int, input().split()))
AB = [list(map(int, input().split())) for i in range(M)]

AB.reverse()

uni = Union(N + 1)
L = []
Ans = N * (N - 1) // 2
for i in AB:
  L.append(Ans)
  if uni.root(i[0]) != uni.root(i[1]):
    Ans -= uni.size(i[0]) * uni.size(i[1])
    uni.merge(i[0], i[1])

for i in L[::-1]:
  print(i)

# Optimized solution
class Union:

  def __init__(self, num):
    self.T = [-1 for i in range(num)]

  def root(self, x):
    if self.T[x] < 0: return x
    return self.root(self.T[x])

  def size(self, x):
    return -self.T[self.root(x)]

  def merge(self, x, y):
    a = self.root(x)
    b = self.root(y)
    if a == b: return False
    if self.size(a) < self.size(b): a, b = b, a
    self.T[a] += self.T[b]
    self.T[b] = a
    return True

N, M = list(map(int, input().split()))
AB = [list(map(int, input().split())) for i in range(M)]

AB.reverse()

uni = Union(N + 1)
L = []
Ans = N * (N - 1) // 2
for i in AB:
  L.append(Ans)
  a = uni.root(i[0])
  b = uni.root(i[1])
  if a != b:
    Ans -= uni.size(a) * uni.size(b)
    uni.merge(i[0], i[1])

for i in L[::-1]:
  print(i)
# Original solution
N, M = list(map(int, input().split()))
B = [list(map(int, input().split())) for _ in range(M)]

pt = []
G = [0 for x in range(N+1)]
C = [1 for x in range(N+1)]

def find(x):
    while G[x] != 0:
        x = G[x]
    return x

cnt = 0
while len(B):
    x, y = B.pop()
    wx = find(x)
    wy = find(y)
    if wx is wy:
        pt.append(0)
    else:
        pt.append(C[wx] * C[wy])
        C[wx] += C[wy]
        G[wy] = wx

    #print(G)

cnt = 0
for _ in range(M):
    cnt += pt.pop()
    print(cnt)


# Optimized solution
N, M = list(map(int, input().split()))
B = [list(map(int, input().split())) for _ in range(M)]

pt = []
G = [[None, 1] for x in range(N+1)]

def find(x):
    n = G[x]
    c = []
    while not n[0] is None:
        c.append(n)
        n = n[0]
    for ci in c:
        ci[0] = n
    return n

cnt = 0
while len(B):
    x, y = B.pop()
    wx = find(x)
    wy = find(y)
    if wx is wy:
        pt.append(0)
    else:
        pt.append(wx[1] * wy[1])
        wx[1] += wy[1]
        wy[0] = wx

    #print(G)

cnt = 0
for _ in range(M):
    cnt += pt.pop()
    print(cnt)
# 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)

N, M, *X = list(map(int,open(0).read().split()))

uf = UnionFind(N + 1)

S = N * (N - 1) // 2
r = [S]

while X:
  b, a = X.pop(), X.pop()
  if not uf.same(a, b):
    S -= uf.size(a) * uf.size(b)
  r.append(S)
  uf.union(a, b)

for a in r[-2::-1]:
  print(a)

# Optimized solution
def find(x):
  if P[x] < 0:
    return x
  else:
    P[x] = find(P[x])
    return P[x]

N, M, *X = list(map(int,open(0).read().split()))
P = [-1] * (N + 1)
S = N * (N - 1) // 2
r = [S]

while X:
  b, a = find(X.pop()), find(X.pop())
  if a != b:
    S -= P[a] * P[b]
    if P[a] > P[b]:
      a, b = b, a
    P[a] += P[b]
    P[b] = a
  r.append(S)

for a in r[-2::-1]:
  print(a)
# Original solution
def find(x):
  if P[x] < 0:
    return x
  else:
    P[x] = find(P[x])
    return P[x]

N, M, *X = list(map(int,open(0).read().split()))
P = [-1] * (N + 1)
S = N * (N - 1) // 2
r = [S]

while X:
  b, a = find(X.pop()), find(X.pop())
  if a != b:
    S -= P[a] * P[b]
    if P[a] > P[b]:
      a, b = b, a
    P[a] += P[b]
    P[b] = a
  r.append(S)

for a in r[-2::-1]:
  print(a)

# Optimized solution
def find(x):
  if P[x] < 0:
    return x
  else:
    P[x] = find(P[x])
    return P[x]

N, M, *X = map(int,open(0).read().split())
P = [-1] * (N + 1)
S = N * (N - 1) // 2
r = [S]

while X:
  b, a = find(X.pop()), find(X.pop())
  if a != b:
    S -= P[a] * P[b]
    if P[a] > P[b]:
      a, b = b, a
    P[a] += P[b]
    P[b] = a
  r.append(S)

r.pop()
print(*reversed(r), sep='\n')
# Original solution
from functools import reduce
from operator import mul

def cmb(n,r):
  r = min(r, n-r)
  if r==0: return 1
  if r<0: return 0
  over = reduce(mul, list(range(n, n-r, -1)))
  under = reduce(mul, list(range(1,r+1)))
  return over//under

class UnionFind:
  def __init__(self, n):
    self.par = [i for i in range(n)]
    self.size = [1]*n
    self.rank = [0]*n
  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 unit(self, x, y):
    x = self.find(x)
    y = self.find(y)
    if x==y:
      return
    elif self.rank[x]<self.rank[y]:
      self.par[x] = y
      self.size[y] += self.size[x]
      return
    elif self.rank[y]<self.rank[x]:
      self.par[y] = x
      self.size[x] += self.size[y]
    else:
      self.par[y] = x
      self.size[x] += self.size[y]
      self.rank[x] += 1
      
  def same(self, x, y):
    return self.find(x)==self.find(y)
  
  def count(self, x):
    return self.size[x]

N, M = list(map(int, input().split()))
bridge = []
u = UnionFind(N)
m = cmb(N,2)
ans = [m]

for i in range(M):
  A, B = list(map(int, input().split()))
  bridge += [(A,B)]
  
for i in range(M-1,0,-1):
  a, b = bridge[i]
  if u.same(a-1,b-1):
    ans += [m]
    continue
  pa = u.find(a-1)
  pb = u.find(b-1)
  m -= u.count(pa)*u.count(pb)
  ans += [m]
  u.unit(a-1,b-1)

for i in range(M-1,-1,-1):
  print((ans[i]))
  

# Optimized solution
class UnionFind:
  def __init__(self, n):
    self.par = [i for i in range(n)]
    self.size = [1]*n
    self.rank = [0]*n
  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 unit(self, x, y):
    x = self.find(x)
    y = self.find(y)
    if x==y:
      return
    elif self.rank[x]<self.rank[y]:
      self.par[x] = y
      self.size[y] += self.size[x]
      return
    elif self.rank[y]<self.rank[x]:
      self.par[y] = x
      self.size[x] += self.size[y]
    else:
      self.par[y] = x
      self.size[x] += self.size[y]
      self.rank[x] += 1
      
  def same(self, x, y):
    return self.find(x)==self.find(y)
  
  def count(self, x):
    return self.size[x]

N, M, *L = list(map(int, open(0).read().split()))
u = UnionFind(N+1)
m = N*(N-1)//2
ans = []
for a, b in zip(*[iter(L[::-1])]*2):
  ans += [m]
  A = u.find(a)
  B = u.find(b)
  if A!=B:
    na = u.count(A)
    nb = u.count(B)
    u.unit(a,b)
    m -= na*nb

print(('\n'.join(map(str,ans[::-1]))))
# Original solution
import sys
input = sys.stdin.readline

class Node:
    def __init__(self):
        self.is_root = True
        self.parent = None
        self.child_num = 0
    
    def root_node(self):
        node = self
        while not node.is_root:
            node = node.parent
        return node

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

    nodes = [Node() for i in range(N)]

    ab = [list(map(int, input().split())) for i in range(M)]
    
    inc = (N * (N-1)) // 2
    ans = [inc]
    for i in range(M-1, -1, -1):
        a, b = ab[i]
        a -= 1
        b -= 1
        root_a = nodes[a].root_node()
        root_b = nodes[b].root_node()
        if root_a == root_b:# もともと連結成分だった場合
            ans.append(inc)
        else:# 新たに連結成分になった場合
            # if root_b.child_num > root_a.child_num:
            #     tmp = root_a
            #     root_a = root_b
            #     root_b = tmp
            inc -= (root_a.child_num + 1) * (root_b.child_num + 1)
            ans.append(inc)
            root_b.is_root = False
            root_b.parent = root_a
            root_a.child_num += root_b.child_num + 1

    for i in range(M-1, -1, -1):
        print((ans[i]))

if __name__ == "__main__":
    main()



# Optimized solution
import sys
input = sys.stdin.readline

class Node:
    def __init__(self):
        self.is_root = True
        self.parent = None
        self.child_num = 0
    
    def root_node(self):
        node = self
        while not node.is_root:
            node = node.parent
        return node

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

    nodes = [Node() for i in range(N)]

    ab = [list(map(int, input().split())) for i in range(M)]
    
    inc = (N * (N-1)) // 2
    ans = [inc]
    for i in range(M-1, -1, -1):
        a, b = ab[i]
        a -= 1
        b -= 1
        root_a = nodes[a].root_node()
        if root_a != nodes[a]:
            nodes[a].parent = root_a
        root_b = nodes[b].root_node()
        if root_b != nodes[b]:
            nodes[b].parent = root_b
        if root_a == root_b:# もともと連結成分だった場合
            ans.append(inc)
        else:# 新たに連結成分になった場合
            # if root_b.child_num > root_a.child_num:
            #     tmp = root_a
            #     root_a = root_b
            #     root_b = tmp
            inc -= (root_a.child_num + 1) * (root_b.child_num + 1)
            ans.append(inc)
            root_b.is_root = False
            root_b.parent = root_a
            root_a.child_num += root_b.child_num + 1

    for i in range(M-1, -1, -1):
        print((ans[i]))

if __name__ == "__main__":
    main()
# Original solution
import sys
input = sys.stdin.readline

class Node:
    def __init__(self):
        self.is_root = True
        self.parent = None
        self.child_num = 0
    
    def root_node(self):
        node = self
        while not node.is_root:
            node = node.parent
        return node

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

    nodes = [Node() for i in range(N)]

    ab = [list(map(int, input().split())) for i in range(M)]
    
    inc = (N * (N-1)) // 2
    ans = [inc]
    for i in range(M-1, -1, -1):
        a, b = ab[i]
        a -= 1
        b -= 1
        root_a = nodes[a].root_node()
        if root_a != nodes[a]:
            nodes[a].parent = root_a
        root_b = nodes[b].root_node()
        if root_b != nodes[b]:
            nodes[b].parent = root_b
        if root_a == root_b:# もともと連結成分だった場合
            ans.append(inc)
        else:# 新たに連結成分になった場合
            # if root_b.child_num > root_a.child_num:
            #     tmp = root_a
            #     root_a = root_b
            #     root_b = tmp
            inc -= (root_a.child_num + 1) * (root_b.child_num + 1)
            ans.append(inc)
            root_b.is_root = False
            root_b.parent = root_a
            root_a.child_num += root_b.child_num + 1

    for i in range(M-1, -1, -1):
        print((ans[i]))

if __name__ == "__main__":
    main()



# Optimized solution
import sys
input = sys.stdin.readline

class Node:
    def __init__(self):
        self.is_root = True
        self.parent = None
        self.child_num = 0
    
    def root_node(self):
        node = self
        while not node.is_root:
            node = node.parent
        return node

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

    nodes = [Node() for i in range(N)]

    ab = [list(map(int, input().split())) for i in range(M)]
    
    inc = (N * (N-1)) // 2
    ans = [inc]
    for i in range(M-1, -1, -1):
        a, b = ab[i]
        a -= 1
        b -= 1
        root_a = nodes[a].root_node()
        if root_a != nodes[a]:
            nodes[a].parent = root_a
        root_b = nodes[b].root_node()
        if root_b != nodes[b]:
            nodes[b].parent = root_b
        if root_a == root_b:# もともと連結成分だった場合
            ans.append(inc)
        else:# 新たに連結成分になった場合
            if root_b.child_num > root_a.child_num:
                tmp = root_a
                root_a = root_b
                root_b = tmp
            inc -= (root_a.child_num + 1) * (root_b.child_num + 1)
            ans.append(inc)
            root_b.is_root = False
            root_b.parent = root_a
            root_a.child_num += root_b.child_num + 1

    for i in range(M-1, -1, -1):
        print((ans[i]))

if __name__ == "__main__":
    main()
# Original solution
import sys
sys.setrecursionlimit(10 ** 7)


class UnionFind:
    def __init__(self, size: int):
        self.parent = [-1 for _ in range(size)]
        self.size = [1 for _ in range(size)]

    def unite(self, x, y):
        px = self.find(x)
        py = self.find(y)
        if px != py:
            if self.parent[px] > self.parent[py]:
                self.parent[py] = px
                self.parent[px] -= 1
                self.size[px] += self.size[py]
                self.size[py] = 0
            else:
                self.parent[px] = py
                self.parent[py] -= 1
                self.size[py] += self.size[px]
                self.size[px] = 0
        return

    def find(self, x: int) -> int:
        if self.parent[x] < 0:
            return x
        self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def is_same(self, x: int, y: int) -> bool:
        return self.find(x) == self.find(y)


def main():
    # input
    N, M = map(int, input().split())
    brs = [list(map(int, input().split())) for _ in range(M)]

    # solve
    # ref: http://drken1215.hatenablog.com/entry/2019/03/03/224600
    # ref: https://atcoder.jp/contests/abc120/submissions/4450601
    uf = UnionFind(N)
    ans = [N*(N-1)//2]
    for i in range(M-1, 0, -1):
        a, b = brs[i][0], brs[i][1]
        a, b = a-1, b-1
        p1 = uf.find(a)
        p2 = uf.find(b)
        if p1 != p2:
            ans.append(ans[-1] - uf.size[p1]*uf.size[p2])
        else:
            ans.append(ans[-1])
        uf.unite(p1, p2)
    return ans


print(*list(reversed(main())), sep="\n")


# Optimized solution
class UnionFind:
    def __init__(self, size: int):
        self.parent = [-1 for _ in range(size)]

    def unite(self, x, y):
        px = self.find(x)
        py = self.find(y)
        if px == py:
            return
        if self.size(px) > self.size(py):
            px, py = py, px
        self.parent[py] += self.parent[px]
        self.parent[px] = py
        return

    def find(self, x: int) -> int:
        if self.parent[x] < 0:
            return x
        self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

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

    def is_same(self, x: int, y: int) -> bool:
        return self.find(x) == self.find(y)


def main():
    # input
    N, M = map(int, input().split())
    A, B = [], []

    for _ in range(M):
        a, b = map(int, input().split())
        A.append(a-1)
        B.append(b-1)

    # solve
    # ref: http://drken1215.hatenablog.com/entry/2019/03/03/224600
    # ref: https://atcoder.jp/contests/abc120/submissions/4450601
    uf = UnionFind(N)
    ans = [N*(N-1)//2]
    for i in range(M-1, 0, -1):
        p1 = uf.find(A[i])
        p2 = uf.find(B[i])
        if p1 != p2:
            ans.append(ans[-1] - uf.size(p1)*uf.size(p2))
        else:
            ans.append(ans[-1])
        uf.unite(p1, p2)
    return ans


print(*list(reversed(main())), sep="\n")
# Original solution
import collections as co
import copy as cp
L = co.deque()
N, M = list(map(int, input().split()))
def check(n, x, done):
    try:
        if n in dic[x]:
            return True
        else:
            if x in done or len(dic[x]) == 0:
                return False
            done.add(x)
            for j in dic[x]:
                if j in done:
                    continue
                if check(n, j, cp.copy(done)):
                    return True
    except:
        return False

for i in range(M):
    L.append(list(map(int, input().split())))
for i in range(M):
    L.popleft()
    dic = {}
    cnt = 0
    for j in range(len(L)):
      dic.setdefault(L[j][0], set())
      dic[L[j][0]].add(L[j][1])
      dic.setdefault(L[j][1], set())
      dic[L[j][1]].add(L[j][0])
    for key in [i+1 for i in range(N)]:
        for n in range(key+1, N+1):
            done = set()
            if check(n, key, done):
                continue
            else:
                cnt += 1
    print(cnt)

# Optimized solution
import collections as co
L = co.deque()
N, M = list(map(int, input().split()))
def check(n, x, done):
    try:
        if n in dic[x]:
            return True
        else:
            if x in done or len(dic[x]) == 0:
                return False
            done.add(x)
            for j in dic[x]:
                if j in done:
                    continue
                if check(n, j, done):
                    return True
    except:
        return False

for i in range(M):
    L.append(list(map(int, input().split())))
for i in range(M):
    L.popleft()
    dic = {}
    cnt = 0
    for j in range(len(L)):
      dic.setdefault(L[j][0], set())
      dic[L[j][0]].add(L[j][1])
      dic.setdefault(L[j][1], set())
      dic[L[j][1]].add(L[j][0])
    for key in [i+1 for i in range(N)]:
        for n in range(key+1, N+1):
            done = set()
            if check(n, key, done):
                continue
            else:
                cnt += 1
    print(cnt)
# Original solution
N, M = [int(i) for i in input().split()]
parent = [i for i in range(N+1)]
node_num = [1 for i in range(N+1)]
def find(x):
    if parent[x] == x:
        return x
    else:
        parent[x] = find(parent[x])
        return parent[x]

def find_for(x):
    while parent[x] != x:
        x = parent[x]
    return x

bridge = []
for i in range(M):
    A, B = [int(i) for i in input().split()]
    bridge.append([A, B])

bridge = bridge[::-1]
ans_rev = [N*(N-1)//2]
combi = 0
for i in range(M-1):
    A, B = bridge[i]
    r_A = find_for(A)
    r_B = find_for(B)
    if r_A != r_B:
        parent[r_B] = r_A
        combi += node_num[r_B] * node_num[r_A]
        node_num[r_A] += node_num[r_B]
    ans_rev.append(N*(N-1)//2-combi)

ans = ans_rev[::-1]
print(*ans, sep="\n")


# Optimized solution
import sys
sys.setrecursionlimit(10**6)

N, M = [int(i) for i in input().split()]
parent = [i for i in range(N+1)]
node_num = [1 for i in range(N+1)]
def find(x):
    if parent[x] == x:
        return x
    else:
        parent[x] = find(parent[x])
        return parent[x]

bridge = []
for i in range(M):
    A, B = [int(i) for i in input().split()]
    bridge.append([A, B])

bridge = bridge[::-1]
ans_rev = [N*(N-1)//2]
combi = 0
for i in range(M-1):
    A, B = bridge[i]
    r_A = find(A)
    r_B = find(B)
    if r_A != r_B:
        parent[r_B] = r_A
        combi += node_num[r_B] * node_num[r_A]
        node_num[r_A] += node_num[r_B]
    ans_rev.append(N*(N-1)//2-combi)

ans = ans_rev[::-1]
print(*ans, sep="\n")