Buggy python submission (verdict: Runtime Error):
class UnionFind():
    def __init__(self, n):
        self.parent = [-1 for _ in range(n)]
        # 正==子: 根の頂点番号 / 負==根: 連結頂点数

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

    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        else:
            if self.size(x) < self.size(y):
                x, y = y, x
            self.parent[x] += self.parent[y]
            self.parent[y] = x

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

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

    def is_root(self, x):
        return self.parent[x] < 0

N, M, *hashi = map(int, open(0).read().split()) #ターミナルだと答え出てこないので注意、最終手段(10**5行で100msほど早くなる)
uf = UnionFind(N)
lis = [0]*M
lis[M-1] = N*(N-1)//2

for i in range(M-2,-1,-1):
    x = hashi[i+1][0]-1
    y = hashi[i+1][1]-1
    if uf.same(x,y):
        lis[i] = tmp
    else:
        xs = uf.size(x)
        ys = uf.size(y)
        uf.unite(x,y)
        tmp = lis[i+1] - xs*ys
        lis[i] = tmp
        if not tmp:
            break 
for i in range(M):
    print(lis[i])


Fixed submission:
class UnionFind():
    def __init__(self, n):
        self.parent = [-1 for _ in range(n)]
        # 正==子: 根の頂点番号 / 負==根: 連結頂点数

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

    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        else:
            if self.size(x) < self.size(y):
                x, y = y, x
            self.parent[x] += self.parent[y]
            self.parent[y] = x

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

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

    def is_root(self, x):
        return self.parent[x] < 0

N,M=map(int,input().split())
uf = UnionFind(N)
hashi = [list(map(int,input().split())) for _ in range(M)]
lis = [0]*M
lis[M-1] = N*(N-1)//2

for i in range(M-2,-1,-1):
    x = hashi[i+1][0]-1
    y = hashi[i+1][1]-1
    if uf.same(x,y):
        lis[i] = tmp
    else:
        xs = uf.size(x)
        ys = uf.size(y)
        uf.unite(x,y)
        tmp = lis[i+1] - xs*ys
        lis[i] = tmp
        if not tmp:
            break 
for i in range(M):
    print(lis[i])

Buggy python submission (verdict: Runtime Error):
class UnionFind():
    def __init__(self, n):
        self.parent = [-1 for _ in range(n)]
        # 正==子: 根の頂点番号 / 負==根: 連結頂点数

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

    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        else:
            if self.size(x) < self.size(y):
                x, y = y, x
            self.parent[x] += self.parent[y]
            self.parent[y] = x

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

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

    def is_root(self, x):
        return self.parent[x] < 0

N, M, *hashi = map(int, open(0).read().split()) #ターミナルだと答え出てこないので注意、最終手段(10**5行で100msほど早くなる)
uf = UnionFind(N)
lis = [0]*M
lis[M-1] = N*(N-1)//2

for i in range(M-2,-1,-1):
    x = hashi[i+1][0]-1
    y = hashi[i+1][1]-1
    if uf.same(x,y):
        lis[i] = tmp
    else:
        xs = uf.size(x)
        ys = uf.size(y)
        uf.unite(x,y)
        tmp = lis[i+1] - xs*ys
        lis[i] = tmp
        if not tmp:
            break 
for i in range(M):
    print(lis[i])


Fixed submission:
class UnionFind():
    def __init__(self, n):
        self.parent = [-1 for _ in range(n)]
        # 正==子: 根の頂点番号 / 負==根: 連結頂点数

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

    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        else:
            if self.size(x) < self.size(y):
                x, y = y, x
            self.parent[x] += self.parent[y]
            self.parent[y] = x

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

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

    def is_root(self, x):
        return self.parent[x] < 0

N,M=map(int,input().split())
uf = UnionFind(N)
hashi = [list(map(int,input().split())) for _ in range(M)]
lis = [0]*M
lis[M-1] = N*(N-1)//2

for i in range(M-2,-1,-1):
    x = hashi[i+1][0]-1
    y = hashi[i+1][1]-1
    if uf.same(x,y):
        lis[i] = tmp
    else:
        xs = uf.size(x)
        ys = uf.size(y)
        uf.unite(x,y)
        tmp = lis[i+1] - xs*ys
        lis[i] = tmp
        if not tmp:
            break 
for i in range(M):
    print(lis[i])