Buggy python submission (verdict: Time Limit Exceeded):
from itertools import combinations

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

    # 同じ集合に属するか判定
    def same_check(self, x, y):
        return self.find(x) == self.find(y)

def combi(root_list):
    return sum([a*b for a, b in combinations(root_list, 2)])
    
if __name__ == '__main__':
    N, M = map(int, input().split())
    AB = [list(map(int, input().split())) for _ in range(M)]
    
    AB = AB[::-1]
    
    root_list = [i for i in range(N)]
    root_num = [1]*N
    inconvinience = []
    inconvinience.append(combi(root_num))
    
    tree = UnionFind(N)
    for a, b in AB:
        delta = 0
        if not tree.same_check(a, b):
            delta = tree.size[tree.find(a)]*tree.size[tree.find(b)]
        tree.union(a, b)
        inconvinience.append(inconvinience[-1] - delta)
    
    inconvinience.pop()
    
    for i in inconvinience[::-1]:
        print(i)

Fixed submission:
from itertools import combinations

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

    # 同じ集合に属するか判定
    def same_check(self, x, y):
        return self.find(x) == self.find(y)

def combi(root_list):
    return sum([a*b for a, b in combinations(root_list, 2)])
    
if __name__ == '__main__':
    N, M = map(int, input().split())
    AB = [list(map(int, input().split())) for _ in range(M)]
    
    AB = AB[::-1]
    
    
    inconvinience = []
    inconvinience.append(N*(N-1)//2)
    
    tree = UnionFind(N)
    for a, b in AB:
        delta = 0
        if not tree.same_check(a, b):
            delta = tree.size[tree.find(a)]*tree.size[tree.find(b)]
        tree.union(a, b)
        inconvinience.append(inconvinience[-1] - delta)
    
    inconvinience.pop()
    
    for i in inconvinience[::-1]:
        print(i)

Buggy python submission (verdict: Time Limit Exceeded):
from itertools import combinations

def build_tree(N, root_list, edges):
    for p, q in [edges]:
        p -= 1
        q -= 1
        root_p = get_root(root_list, p)
        root_q = get_root(root_list, q)
        root_now = min(root_p, root_q, p)
        root_list[p] = root_now
        root_list[q] = root_now
        root_list[root_p] = root_now
        root_list[root_q] = root_now
    return root_list

def get_root(root_list, city):
    if root_list[city] == city:
        return city
    else: 
        root_list[city] = get_root(root_list, root_list[city])
        return root_list[city]

def combi(root_list):
    return sum([a*b for a, b in combinations(root_list, 2)])
    
if __name__ == '__main__':
    N, M = map(int, input().split())
    AB = [list(map(int, input().split())) for _ in range(M)]
    
    AB = AB[::-1]
    
    root_list = [i for i in range(N)]
    root_num = [1]*N
    inconvinience = []
    inconvinience.append(combi(root_num))
    
    for edges in AB:
        root_list = build_tree(N, root_list,edges)
        root_list = [get_root(root_list, i) for i in range(N)]
        root_num = [0]*N
        for i in range(N):
            root_num[get_root(root_list, i)] += 1
        inconvinience.append(combi(root_num))
    
    inconvinience.pop()
    
    for i in inconvinience[::-1]:
        print(i)

Fixed submission:
from itertools import combinations

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

    # 同じ集合に属するか判定
    def same_check(self, x, y):
        return self.find(x) == self.find(y)

def combi(root_list):
    return sum([a*b for a, b in combinations(root_list, 2)])
    
if __name__ == '__main__':
    N, M = map(int, input().split())
    AB = [list(map(int, input().split())) for _ in range(M)]
    
    AB = AB[::-1]
    
    
    inconvinience = []
    inconvinience.append(N*(N-1)//2)
    
    tree = UnionFind(N)
    for a, b in AB:
        delta = 0
        if not tree.same_check(a, b):
            delta = tree.size[tree.find(a)]*tree.size[tree.find(b)]
        tree.union(a, b)
        inconvinience.append(inconvinience[-1] - delta)
    
    inconvinience.pop()
    
    for i in inconvinience[::-1]:
        print(i)