Buggy python submission (verdict: Runtime Error):
n,m=map(int,input().split())
A=[]
for i in range(m):
  a,b=map(int,input().split())
  A.append([a,b])
A=A[::-1]
Ans=[]
grid=[]

for i in range(m):
  if i==0:
    Ans.append(0)
    grid.append(A[0])
  else:
    for g in range(len(grid)):
      if A[0] in grid[g] :
        if A[1] in grid[g]:
          Ans.append(Ans[i-1])
          break
        else:
          for k in range(len(grid)):
            if A[1] in grid[k]:
              grid[g]=list(set(grid[g]+grid[k]))
              Ans.append((len(grid[g])*len(grid[g])-1)//2)
              break
            else:
              grid[g]+=[A[1]]
              Ans.append((len(grid[g])*len(grid[g])-1)//2)
      elif A[1] in grid[g]:
        if A[0] in grid[g]:
          Ans.append(Ans[i-1])
          break
        else:
          for k in range(len(grid)):
            if A[0] in grid[k]:
              grid[g]=list(set(grid[g]+grid[k]))
              Ans.append((len(grid[g])*len(grid[g])-1)//2)
              break
            else:
              grid[g]+=[A[0]]
              Ans.append((len(grid[g])*len(grid[g])-1)//2)
      else:
        grid+=A[i]
        Ans.append(Ans[i-1]+(len(grid[g])*len(grid[g])-1)//2)
        
print(1)
  

Fixed submission:
from collections import deque
class UnionFind():
    def __init__(self,num):
        self.n = num         #class内変数nに、外部から入力した値numを代入
        self.parents = [-1 for i in range(self.n)]
          #parentsは要素の親(1こ上のやつ)番号0~n-1を格納、自分が最親なら-(要素数)を格納(初期値は-1)

    #xの最親は誰？
    def find(self,x):
        if self.parents[x]<0:
            return x
        else:
            self.parents[x]=self.find(self.parents[x]) #再帰して1番上までいってる
                #調べながらparentsの値を更新してる！（経路圧縮）
            return self.parents[x]

    #結合せよ
    #xの親とyの親をくっつける
    def union(self,x,y):
        xx=self.find(x)  #xxはxの最親
        yy=self.find(y)  #yyはyの最親
        if xx==yy:
            return     #同じ屋根の下にあった場合は何もしない
        else:
            size_xx=abs(self.parents[xx]) #xが含まれる木のサイズ
            size_yy=abs(self.parents[yy]) #yが含まれる木のサイズ
            if size_xx>size_yy:
                xx,yy=yy,xx  #yyの方が大きい木、ってことにする

            self.parents[yy]+=self.parents[xx] #大きい木のサイズ更新
            self.parents[xx]=yy   #サイズが小さい木を大きい木に接ぐ

    #xの属する木の大きさ（まあunionでも使ったけど）
    def size(self,x):
        xx=self.find(x)
        return abs(self.parents[xx])

    #xとyはこの空の続く場所にいますか　いつものように笑顔でいてくれますか　今はただそれを願い続ける
    def same(self,x,y):
        return True if self.find(x)==self.find(y) else False

    #xと　同じ木にいる　メンバーは？
    def members(self,x):
        xx=self.find(x)
        return [i for i in range(self.n) if self.find(i)==xx]
             #ifの条件式に漏れたら無視

    #最親だけを並べあげる
    def roots(self):
        return [i for i,x in enumerate(self.parents) if x < 0]
        #いやこれは天才すぎる、basisのenumerate.py参照

    #すべての最親について、メンバーを辞書で
    def all_group_members(self):
        return {r:self.members(r) for r in self.roots()}

    #グループ分けどうなりましたか、２重リストで
    def state_grouping(self):
        return list(self.all_group_members().values())

    #出力用
    def __str__(self):
        return "\n".join("{}: {}".format(r,self.members(r)) for r in self.roots())
        #"\n"はただの改行コード
        #str(辞書)を改行しながら表示する
        #print(インスタンス)で__str__に飛ぶ
        #出力過程で、membersで全要素にfindをしてる→逐一経路圧縮されてる！


n,m=map(int,input().split())
uf=UnionFind(n)
A=[]
for i in range(m):
    A.append(list(map(int,input().split())))
ans=[0 for i in range(m)] #つながるかず

for i in range(1,m):
    q,w=A[-i] ; q-=1 ; w-=1 ; 
    if uf.same(q,w) :
      ans[i]=ans[i-1]
      continue
    a=uf.size(q) ; b=uf.size(w)
    ans[i]=ans[i-1]-a*(a-1)//2-b*(b-1)//2+(a+b)*(a+b-1)//2
    uf.union(q,w)

    
for i in range(m):

    print(n*(n-1)//2 - ans[m-1-i])