import sys
sys.setrecursionlimit(1000000000)
input = sys.stdin.readline
class UnionFind():
   # 作りたい要素数nで初期化
   # 使用するインスタンス変数の初期化
   def __init__(self, n):
       self.n = n
       # root[x]<0ならそのノードが根かつその値が木の要素数
       # rootノードでその木の要素数を記録する
       self.root = [-1]*(n+1)
       # 木をくっつける時にアンバランスにならないように調整する
       self.rnk = [0]*(n+1)
   # ノードxのrootノードを見つける
   def Find_Root(self, x):
       if(self.root[x] < 0):
           return x
       else:
           # ここで代入しておくことで、後の繰り返しを避ける
           self.root[x] = self.Find_Root(self.root[x])
           return self.root[x]
   # 木の併合、入力は併合したい各ノード
   def Unite(self, x, y):
       # 入力ノードのrootノードを見つける
       x = self.Find_Root(x)
       y = self.Find_Root(y)
       # すでに同じ木に属していた場合
       if(x == y):
           return
       # 違う木に属していた場合rnkを見てくっつける方を決める
       elif(self.rnk[x] > self.rnk[y]):
           self.root[x] += self.root[y]
           self.root[y] = x
       else:
           self.root[y] += self.root[x]
           self.root[x] = y
           # rnkが同じ（深さに差がない場合）は1増やす
           if(self.rnk[x] == self.rnk[y]):
               self.rnk[y] += 1
   # xとyが同じグループに属するか判断
   def isSameGroup(self, x, y):
       return self.Find_Root(x) == self.Find_Root(y)
   # ノードxが属する木のサイズを返す
   def Count(self, x):
       return -self.root[self.Find_Root(x)]
n,m=map(int,input().split())
e=[tuple(map(int,input().split())) for _ in range(m)]
e.reverse()
h=UnionFind(n)
ans=[0]*m
k=n*(n-1)//2
for i in range(m):
    ans[i]=k
    s,t=e[i]
    if not h.isSameGroup(s,t):
        k-=h.Count(s)*h.Count(t)
        h.Unite(s,t)
for i in ans[::-1]:
    print(i) import sys sys sys.setrecursionlimit(1000000000) sys.setrecursionlimit sys setrecursionlimit 1000000000 input = sys.stdin.readline input sys.stdin.readline sys.stdin sys stdin readline class UnionFind():
   # 作りたい要素数nで初期化
   # 使用するインスタンス変数の初期化
   def __init__(self, n):
       self.n = n
       # root[x]<0ならそのノードが根かつその値が木の要素数
       # rootノードでその木の要素数を記録する
       self.root = [-1]*(n+1)
       # 木をくっつける時にアンバランスにならないように調整する
       self.rnk = [0]*(n+1)
   # ノードxのrootノードを見つける
   def Find_Root(self, x):
       if(self.root[x] < 0):
           return x
       else:
           # ここで代入しておくことで、後の繰り返しを避ける
           self.root[x] = self.Find_Root(self.root[x])
           return self.root[x]
   # 木の併合、入力は併合したい各ノード
   def Unite(self, x, y):
       # 入力ノードのrootノードを見つける
       x = self.Find_Root(x)
       y = self.Find_Root(y)
       # すでに同じ木に属していた場合
       if(x == y):
           return
       # 違う木に属していた場合rnkを見てくっつける方を決める
       elif(self.rnk[x] > self.rnk[y]):
           self.root[x] += self.root[y]
           self.root[y] = x
       else:
           self.root[y] += self.root[x]
           self.root[x] = y
           # rnkが同じ（深さに差がない場合）は1増やす
           if(self.rnk[x] == self.rnk[y]):
               self.rnk[y] += 1
   # xとyが同じグループに属するか判断
   def isSameGroup(self, x, y):
       return self.Find_Root(x) == self.Find_Root(y)
   # ノードxが属する木のサイズを返す
   def Count(self, x):
       return -self.root[self.Find_Root(x)] UnionFind def __init__(self, n):
       self.n = n
       # root[x]<0ならそのノードが根かつその値が木の要素数
       # rootノードでその木の要素数を記録する
       self.root = [-1]*(n+1)
       # 木をくっつける時にアンバランスにならないように調整する
       self.rnk = [0]*(n+1)
   # ノードxのrootノードを見つける
    __init__ self.n = n self.n self n n self.root = [-1]*(n+1) self.root self root [-1]*(n+1) [-1] -1 n+1 n 1 self.rnk = [0]*(n+1) self.rnk self rnk [0]*(n+1) [0] 0 n+1 n 1 self self n n def Find_Root(self, x):
       if(self.root[x] < 0):
           return x
       else:
           # ここで代入しておくことで、後の繰り返しを避ける
           self.root[x] = self.Find_Root(self.root[x])
           return self.root[x]
   # 木の併合、入力は併合したい各ノード
    Find_Root if(self.root[x] < 0):
           return x
       else:
           # ここで代入しておくことで、後の繰り返しを避ける
           self.root[x] = self.Find_Root(self.root[x])
           return self.root[x]
   # 木の併合、入力は併合したい各ノード
    self.root[x] < 0 self.root[x] self.root self root x 0 return x x self.root[x] = self.Find_Root(self.root[x]) self.root[x] self.root self root x self.Find_Root(self.root[x]) self.Find_Root self Find_Root self.root[x] self.root self root x return self.root[x] self.root[x] self.root self root x self self x x def Unite(self, x, y):
       # 入力ノードのrootノードを見つける
       x = self.Find_Root(x)
       y = self.Find_Root(y)
       # すでに同じ木に属していた場合
       if(x == y):
           return
       # 違う木に属していた場合rnkを見てくっつける方を決める
       elif(self.rnk[x] > self.rnk[y]):
           self.root[x] += self.root[y]
           self.root[y] = x
       else:
           self.root[y] += self.root[x]
           self.root[x] = y
           # rnkが同じ（深さに差がない場合）は1増やす
           if(self.rnk[x] == self.rnk[y]):
               self.rnk[y] += 1
   # xとyが同じグループに属するか判断
    Unite x = self.Find_Root(x) x self.Find_Root(x) self.Find_Root self Find_Root x y = self.Find_Root(y) y self.Find_Root(y) self.Find_Root self Find_Root y if(x == y):
           return
       # 違う木に属していた場合rnkを見てくっつける方を決める
       elif(self.rnk[x] > self.rnk[y]):
           self.root[x] += self.root[y]
           self.root[y] = x
       else:
           self.root[y] += self.root[x]
           self.root[x] = y
           # rnkが同じ（深さに差がない場合）は1増やす
           if(self.rnk[x] == self.rnk[y]):
               self.rnk[y] += 1
   # xとyが同じグループに属するか判断
    x == y x y return elif(self.rnk[x] > self.rnk[y]):
           self.root[x] += self.root[y]
           self.root[y] = x
        self.rnk[x] > self.rnk[y] self.rnk[x] self.rnk self rnk x self.rnk[y] self.rnk self rnk y self.root[x] += self.root[y] self.root[x] self.root self root x self.root[y] self.root self root y self.root[y] = x self.root[y] self.root self root y x self.root[y] += self.root[x] self.root[y] self.root self root y self.root[x] self.root self root x self.root[x] = y self.root[x] self.root self root x y if(self.rnk[x] == self.rnk[y]):
               self.rnk[y] += 1
   # xとyが同じグループに属するか判断
    self.rnk[x] == self.rnk[y] self.rnk[x] self.rnk self rnk x self.rnk[y] self.rnk self rnk y self.rnk[y] += 1 self.rnk[y] self.rnk self rnk y 1 self self x x y y def isSameGroup(self, x, y):
       return self.Find_Root(x) == self.Find_Root(y)
   # ノードxが属する木のサイズを返す
    isSameGroup return self.Find_Root(x) == self.Find_Root(y) self.Find_Root(x) == self.Find_Root(y) self.Find_Root(x) self.Find_Root self Find_Root x self.Find_Root(y) self.Find_Root self Find_Root y self self x x y y def Count(self, x):
       return -self.root[self.Find_Root(x)] Count return -self.root[self.Find_Root(x)] -self.root[self.Find_Root(x)] self.root[self.Find_Root(x)] self.root self root self.Find_Root(x) self.Find_Root self Find_Root x self self x x n,m=map(int,input().split()) n map(int,input().split()) map int input().split() ().split () input split m tuple(map(int,input().split())) for _ in range(m) for _ in range(m) _ range(m) range m for _ in range(m) tuple(map(int,input().split())) tuple map(int,input().split()) map int input().split() ().split () input split e=[tuple(map(int,input().split())) for _ in range(m)] e [tuple(map(int,input().split())) for _ in range(m)] e.reverse() e.reverse e reverse h=UnionFind(n) h UnionFind(n) UnionFind n ans=[0]*m ans [0]*m [0] 0 m k=n*(n-1)//2 k n*(n-1)//2 n*(n-1) n n-1 n 1 2 for i in range(m):
    ans[i]=k
    s,t=e[i]
    if not h.isSameGroup(s,t):
        k-=h.Count(s)*h.Count(t)
        h.Unite(s,t) i range(m) range m ans[i]=k ans[i] ans i k s,t=e[i] s e[i] e i t if not h.isSameGroup(s,t):
        k-=h.Count(s)*h.Count(t)
        h.Unite(s,t) not h.isSameGroup(s,t) h.isSameGroup(s,t) h.isSameGroup h isSameGroup s t k-=h.Count(s)*h.Count(t) k h.Count(s)*h.Count(t) h.Count(s) h.Count h Count s h.Count(t) h.Count h Count t h.Unite(s,t) h.Unite h Unite s t for i in ans[::-1]:
    print(i) i ans[::-1] ans ::-1 -1 print(i) print i n,m=map(int,input().split()) map(int,input().split()) n e=[tuple(map(int,input().split())) for _ in range(m)] [tuple(map(int,input().split())) for _ in range(m)] e input = sys.stdin.readline sys.stdin.readline input h=UnionFind(n) UnionFind(n) h s,t=e[i] e[i] s k-=h.Count(s)*h.Count(t) h.Count(s)*h.Count(t) k class UnionFind():
   # 作りたい要素数nで初期化
   # 使用するインスタンス変数の初期化
   def __init__(self, n):
       self.n = n
       # root[x]<0ならそのノードが根かつその値が木の要素数
       # rootノードでその木の要素数を記録する
       self.root = [-1]*(n+1)
       # 木をくっつける時にアンバランスにならないように調整する
       self.rnk = [0]*(n+1)
   # ノードxのrootノードを見つける
   def Find_Root(self, x):
       if(self.root[x] < 0):
           return x
       else:
           # ここで代入しておくことで、後の繰り返しを避ける
           self.root[x] = self.Find_Root(self.root[x])
           return self.root[x]
   # 木の併合、入力は併合したい各ノード
   def Unite(self, x, y):
       # 入力ノードのrootノードを見つける
       x = self.Find_Root(x)
       y = self.Find_Root(y)
       # すでに同じ木に属していた場合
       if(x == y):
           return
       # 違う木に属していた場合rnkを見てくっつける方を決める
       elif(self.rnk[x] > self.rnk[y]):
           self.root[x] += self.root[y]
           self.root[y] = x
       else:
           self.root[y] += self.root[x]
           self.root[x] = y
           # rnkが同じ（深さに差がない場合）は1増やす
           if(self.rnk[x] == self.rnk[y]):
               self.rnk[y] += 1
   # xとyが同じグループに属するか判断
   def isSameGroup(self, x, y):
       return self.Find_Root(x) == self.Find_Root(y)
   # ノードxが属する木のサイズを返す
   def Count(self, x):
       return -self.root[self.Find_Root(x)] class UnionFind():
   # 作りたい要素数nで初期化
   # 使用するインスタンス変数の初期化
   def __init__(self, n):
       self.n = n
       # root[x]<0ならそのノードが根かつその値が木の要素数
       # rootノードでその木の要素数を記録する
       self.root = [-1]*(n+1)
       # 木をくっつける時にアンバランスにならないように調整する
       self.rnk = [0]*(n+1)
   # ノードxのrootノードを見つける
   def Find_Root(self, x):
       if(self.root[x] < 0):
           return x
       else:
           # ここで代入しておくことで、後の繰り返しを避ける
           self.root[x] = self.Find_Root(self.root[x])
           return self.root[x]
   # 木の併合、入力は併合したい各ノード
   def Unite(self, x, y):
       # 入力ノードのrootノードを見つける
       x = self.Find_Root(x)
       y = self.Find_Root(y)
       # すでに同じ木に属していた場合
       if(x == y):
           return
       # 違う木に属していた場合rnkを見てくっつける方を決める
       elif(self.rnk[x] > self.rnk[y]):
           self.root[x] += self.root[y]
           self.root[y] = x
       else:
           self.root[y] += self.root[x]
           self.root[x] = y
           # rnkが同じ（深さに差がない場合）は1増やす
           if(self.rnk[x] == self.rnk[y]):
               self.rnk[y] += 1
   # xとyが同じグループに属するか判断
   def isSameGroup(self, x, y):
       return self.Find_Root(x) == self.Find_Root(y)
   # ノードxが属する木のサイズを返す
   def Count(self, x):
       return -self.root[self.Find_Root(x)] UnionFind m=map(int,input().split()) map(int,input().split()) m k=n*(n-1)//2 n*(n-1)//2 k t=e[i] e[i] t ans=[0]*m [0]*m ans
import sys
sys.setrecursionlimit(1000000000)
input = sys.stdin.readline
class UnionFind():
   # 作りたい要素数nで初期化
   # 使用するインスタンス変数の初期化
   def __init__(self, n):
       self.n = n
       # root[x]<0ならそのノードが根かつその値が木の要素数
       # rootノードでその木の要素数を記録する
       self.root = [-1]*(n+1)
       # 木をくっつける時にアンバランスにならないように調整する
       self.rnk = [0]*(n+1)
   # ノードxのrootノードを見つける
   def Find_Root(self, x):
       if(self.root[x] < 0):
           return x
       else:
           # ここで代入しておくことで、後の繰り返しを避ける
           self.root[x] = self.Find_Root(self.root[x])
           return self.root[x]
   # 木の併合、入力は併合したい各ノード
   def Unite(self, x, y):
       # 入力ノードのrootノードを見つける
       x = self.Find_Root(x)
       y = self.Find_Root(y)
       # すでに同じ木に属していた場合
       if(x == y):
           return
       # 違う木に属していた場合rnkを見てくっつける方を決める
       elif(self.rnk[x] > self.rnk[y]):
           self.root[x] += self.root[y]
           self.root[y] = x
       else:
           self.root[y] += self.root[x]
           self.root[x] = y
           # rnkが同じ（深さに差がない場合）は1増やす
           if(self.rnk[x] == self.rnk[y]):
               self.rnk[y] += 1
   # xとyが同じグループに属するか判断
   def isSameGroup(self, x, y):
       return self.Find_Root(x) == self.Find_Root(y)
   # ノードxが属する木のサイズを返す
   def Count(self, x):
       return -self.root[self.Find_Root(x)]
n,m=map(int,input().split())
e=[tuple(map(int,input().split())) for _ in range(m)]
e.reverse()
h=UnionFind(n)
ans=[0]*m
k=n*(n-1)//2
for i in range(m):
    ans[i]=k
    s,t=e[i]
    if not h.isSameGroup(s,t):
        k-=h.Count(s)*h.Count(t)
        h.Unite(s,t)
for i in ans[::-1]:
    print(i)