CodeEff/ECCO huggingface dataset:
# Original solution
#D問題再チャレンジ
#Union Find

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)
        #print([x,y])
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
            self.size[y] = self.size[x] + self.size[y]
            self.size[x] = 0
        else:
            self.par[y] = x
            if x != y:
                self.size[x] = self.size[x] + self.size[y]
                self.size[y] = 0
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

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

n, m = list(map(int, input().split()))

uf = UnionFind(n)

con = [0] * (m+1)#convenience
x = [0] * (m+1)
y = [0] * (m+1)

con[m] = 0

for i in range(1,m+1):
    x[i], y[i] = list(map(int, input().split()))
    #print([x,y])
    
for j in range(m-1,0,-1):
    #print([x[j+1],y[j+1]])
    uf.union(x[j+1],y[j+1])
    
    for k in range(1,n+1):
        s = uf.size[k]
        con[j] = con[j] + int(s*(s-1) / 2)
    
    #print(uf.size)

N = int(n * (n-1) / 2)

for i in range(1,m+1):
    print((N-con[i]))

# Optimized solution
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)
        self.con = [0] * (m+1)#convenience

    # 検索
    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, j):
        x = self.find(x)
        y = self.find(y)
        if x != y:
            self.con[j] = self.con[j+1] + self.size[x] * self.size[y]
        else:
            self.con[j] = self.con[j+1]
        #print([x,y])
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
            self.size[y] = self.size[x] + self.size[y]
            self.size[x] = 0
        else:
            self.par[y] = x
            if x != y:
                self.size[x] = self.size[x] + self.size[y]
                self.size[y] = 0
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

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

n, m = list(map(int, input().split()))

uf = UnionFind(n)

x = [0] * (m+1)
y = [0] * (m+1)


for i in range(1,m+1):
    x[i], y[i] = list(map(int, input().split()))
    #print([x,y])
    
for j in range(m-1,0,-1):
    #print([x[j+1],y[j+1]])
    uf.union(x[j+1],y[j+1],j)
    
    #print(uf.size)
    #print(uf.con)

N = int(n * (n-1) / 2)

for i in range(1,m+1):
    print((N-uf.con[i]))
# Original solution
#要素の根を探す関数
def find_root(n):
    while(parts[n-1][0]!=n-1):
        n=parts[n-1][0]+1
    return tuple(parts[n-1])

#入力を受け取る
N,M=list(map(int,input().split()))
AB=[list(map(int,input().split())) for i in range(M)]

#partsの1つ目は根の番号、2つ目は深さ、3つ目は接続されている要素数
parts=[[i,1,1] for i in range(N)]
#全部壊れた時の不便度はN(N-1)
ans=[N*(N-1)//2]

#橋の数-1だけ処理を行う（橋が全部かかっているときは不便度0なので）
for i in range(M-1):
#一番最後に壊れた橋を探す
    ab=AB.pop()
#それぞれの要素の根を探す
    a=find_root(ab[0])
    b=find_root(ab[1])
#木構造が浅い方をaとする
    if a[1]<=b[1]:
        a,b=a,b
    else:
        b,a=a,b
#根が同一ならば処理不要
    if a[0]==b[0]:
        ans.append(ans[-1])
#根が違うのであれば、以後木をくっつける処理を行う
    else:
#要素x個の木と要素y個の木が繋がれば不便度はxyだけ減る
        ans.append(ans[-1]-a[2]*b[2])
#bの根にaを接続する
        parts[b[0]][0]=parts[a[0]][0]
#接続後のaの深さは(aの深さ)と(bの深さ+1)の大きい方
        parts[a[0]][1]=max(parts[a[0]][1],parts[b[0]][1]+1)
#aの要素数+bの要素数が接続後のaの要素数
        parts[a[0]][2]+=parts[b[0]][2]
#答えを出力
for i in reversed(ans):
    print(i)

# Optimized solution
#要素の根を探す関数
def find_root(n):
    while(parts[n-1][0]!=n-1):
        n=parts[n-1][0]+1
    return tuple(parts[n-1])

#入力を受け取る
N,M=list(map(int,input().split()))
AB=[list(map(int,input().split())) for i in range(M)]

#partsの1つ目は根の番号、2つ目は深さ、3つ目は接続されている要素数
parts=[[i,1,1] for i in range(N)]
#全部壊れた時の不便度はN(N-1)
ans=[N*(N-1)//2]

#橋の数-1だけ処理を行う（橋が全部かかっているときは不便度0なので）
for i in range(M-1):
#一番最後に壊れた橋を探す
    ab=AB.pop()
#それぞれの要素の根を探す
    a=find_root(ab[0])
    b=find_root(ab[1])
#木構造が深い方をaとする
    if a[1]>=b[1]:
        a,b=a,b
    else:
        b,a=a,b
#根が同一ならば処理不要
    if a[0]==b[0]:
        ans.append(ans[-1])
#根が違うのであれば、以後木をくっつける処理を行う
    else:
#要素x個の木と要素y個の木が繋がれば不便度はxyだけ減る
        ans.append(ans[-1]-a[2]*b[2])
#bの根にaを接続する
        parts[b[0]][0]=parts[a[0]][0]
#接続後のaの深さは(aの深さ)と(bの深さ+1)の大きい方
        parts[a[0]][1]=max(parts[a[0]][1],parts[b[0]][1]+1)
#aの要素数+bの要素数が接続後のaの要素数
        parts[a[0]][2]+=parts[b[0]][2]
#答えを出力
for i in reversed(ans):
    print(i)
# Original solution
#要素の根を探す関数
def find_root(n,parts):
    root=[]
    n=n-1
    #根をnとして返す
    while(parts[n][0]!=n):
        root.append(n)
        n=parts[n][0]
    #途中で見つけた要素は全てnに繋ぐことで経路圧縮
    for i in root:
        parts[i][0]=n
    #partsをタプルで返す
    return tuple(parts[n])

#入力を受け取る
N,M=list(map(int,input().split()))
AB=[list(map(int,input().split())) for i in range(M)]

#partsの1つ目は根の番号、2つ目は深さ、3つ目は接続されている要素数
parts=[[i,1,1] for i in range(N)]
ans=[N*(N-1)//2]

#橋の数-1だけ処理を行う（橋が全部かかっているときは不便度0なので）
for i in range(M-1):
    #一番最後に壊れた橋を探す
    ab=AB.pop()
    #それぞれの要素の根を探す
    a=find_root(ab[0],parts)
    b=find_root(ab[1],parts)
    #木構造が深い方をaとする
    if a[1]>=b[1]:
        a,b=a,b
    else:
        b,a=a,b
    #根が同一ならば処理不要
    if a[0]==b[0]:
        ans.append(ans[-1])
    #根が違うのであれば、以後木をくっつける処理を行う
    else:
    #要素x個の木と要素y個の木が繋がれば不便度はxyだけ減る
        ans.append(ans[-1]-a[2]*b[2])
    #bの根にaを接続する
        parts[b[0]][0]=parts[a[0]][0]
    #接続後のaの深さは(aの深さ)と(bの深さ+1)の大きい方
        parts[a[0]][1]=max(parts[a[0]][1],parts[b[0]][1]+1)
    #aの要素数+bの要素数が接続後のaの要素数
        parts[a[0]][2]+=parts[b[0]][2]
#答えを出力
for i in reversed(ans):
    print(i)

# Optimized solution
#要素の根を探す関数
def find_root(n,parts):
    n=n-1
    #partsをタプルで返す
    if parts[n][0]==n:
        return tuple(parts[n])
    else:
        return find_root(parts[n][0]+1,parts)

#入力を受け取る
N,M=list(map(int,input().split()))
AB=[list(map(int,input().split())) for i in range(M)]

#partsの1つ目は根の番号、2つ目は深さ、3つ目は接続されている要素数
parts=[[i,1,1] for i in range(N)]
ans=[N*(N-1)//2]

#橋の数-1だけ処理を行う（橋が全部かかっているときは不便度0なので）
for i in range(M-1):
    #一番最後に壊れた橋を探す
    ab=AB.pop()
    #それぞれの要素の根を探す
    a=find_root(ab[0],parts)
    b=find_root(ab[1],parts)
    #木構造が深い方をaとする
    if a[1]>=b[1]:
        a,b=a,b
    else:
        b,a=a,b
    #根が同一ならば処理不要
    if a[0]==b[0]:
        ans.append(ans[-1])
    #根が違うのであれば、以後木をくっつける処理を行う
    else:
    #要素x個の木と要素y個の木が繋がれば不便度はxyだけ減る
        ans.append(ans[-1]-a[2]*b[2])
    #bの根にaを接続する
        parts[b[0]][0]=parts[a[0]][0]
    #接続後のaの深さは(aの深さ)と(bの深さ+1)の大きい方
        parts[a[0]][1]=max(parts[a[0]][1],parts[b[0]][1]+1)
    #aの要素数+bの要素数が接続後のaの要素数
        parts[a[0]][2]+=parts[b[0]][2]
#答えを出力
for i in reversed(ans):
    print(i)
# 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 unite(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)
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i)==root]
    def roots(self):
        return [i for i,x in enumerate(self.parents) if x<0]
    def group_count(self):
        return len(self.roots())
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
n,m=list(map(int,input().split()))
ab=[list(map(int,input().split())) for _ in range(m)]
ans=[0]*m
ans[-1]=n*(n-1)//2
uf=UnionFind(n)
for i in range(m-1,0,-1):
  ai=ab[i][0]-1
  bi=ab[i][1]-1
  if uf.same(ai,bi):
    ans[i-1]=ans[i]
  else:
    ans[i-1]=ans[i]-uf.size(ai)*uf.size(bi)
    uf.unite(ai,bi)
print(('\n'.join(map(str,ans))))

# Optimized 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 unite(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)
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i)==root]
    def roots(self):
        return [i for i,x in enumerate(self.parents) if x<0]
    def group_count(self):
        return len(self.roots())
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
n,m=list(map(int,input().split()))
ab=[list(map(int,input().split())) for i in range(m)]
uf=UnionFind(n)
ans=[0]*m
ans[-1]=n*(n-1)//2
for i in range(1,m)[::-1]:
  a,b=ab[i][0]-1,ab[i][1]-1
  if uf.same(a,b):
    ans[i-1]=ans[i]
  else:
    ans[i-1]=ans[i]-uf.size(a)*uf.size(b)
    uf.unite(a,b)
print(('\n'.join(map(str,ans))))
# Original solution
class UnionFind:
    def __init__(self, size):
        self.parent = [-1] * size
        self.rank = [0] * size
        self.num = self.parent

    def unite(self, n1, n2):
        rank, parent, num = self.rank, self.parent, self.num
        root, root_2 = self.find(n1), self.find(n2)

        if rank[root] > rank[root_2]:
            pass
        elif rank[root] < rank[root_2]:
            root_2, root = root, root_2
        else:
            rank[root] += 1

        num[root] += num[root_2]
        parent[root_2] = root
        return root

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


n, m = list(map(int, input().split()))
ab = [tuple(map(int, input().split())) for _ in range(m)]

ans = n * (n - 1) // 2
t = UnionFind(n + 1)
v = []

for a, b in reversed(ab):
    v.append(ans)
    root_a = t.find(a)
    root_b = t.find(b)
    if root_a == root_b:
        pass
    else:
        ans -= t.num[root_a] * t.num[root_b]
        t.unite(a, b)

for x in reversed(v):
    print(x)


# Optimized solution
class UnionFind:
    def __init__(self, size):
        self.parent = [-1] * size
        self.rank = [0] * size
        self.num = self.parent

    def unite(self, n1, n2):
        rank, parent, num = self.rank, self.parent, self.num
        root, root_2 = self.find(n1), self.find(n2)

        if rank[root] > rank[root_2]:
            pass
        elif rank[root] < rank[root_2]:
            root_2, root = root, root_2
        else:
            rank[root] += 1

        num[root] += num[root_2]
        parent[root_2] = root
        return root

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


n, m = list(map(int, input().split()))
ab = [tuple(map(int, input().split())) for _ in range(m)]

ans = n * (n - 1) // 2
t = UnionFind(n + 1)
v = []

for a, b in reversed(ab):
    v.append(ans)
    root_a = t.find(a)
    root_b = t.find(b)
    if root_a == root_b:
        pass
    else:
        ans -= t.num[root_a] * t.num[root_b]
        t.unite(a, b)

for x in reversed(v):
    print(x)
# Original solution
import sys
input = sys.stdin.readline

def readlines(n):
    for _ in range(n):
        a, b = list(map(int, input().split()))
        yield a, b

def main():
    n, m = list(map(int, input().split()))
    bridges = list(readlines(m))

    tree = list(range(n+1))
    rank = [1] * (n+1)

    def root(v):
        while tree[v] != v:
            tree[v] = tree[tree[v]]
            v = tree[v]
        return v

    fuben = n*(n-1)//2

    for a, b in bridges[::-1]:
        x = root(a)
        y = root(b)

        if x == y:
            yield str(fuben)
            continue
        
        yield str(fuben)
        fuben -= rank[x]*rank[y]

        if rank[x] < rank[y]:
            tree[x] = y
            rank[y] += rank[x]
        else:
            tree[y] = x
            rank[x] += rank[y]

print(("\n".join(reversed(list(main())))))


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

def readlines(n):
    for _ in range(n):
        a, b = list(map(int, input().split()))
        yield a, b

n, m = list(map(int, input().split()))
bridges = list(readlines(m))

tree = list(range(n+1))
rank = [1] * (n+1)

def root(v):
    while tree[v] != v:
        tree[v] = tree[tree[v]]
        v = tree[v]
    return v

def main():
    fuben = n*(n-1)//2

    for a, b in bridges[::-1]:
        x = root(a)
        y = root(b)

        if x == y:
            yield str(fuben)
            continue
        
        yield str(fuben)
        fuben -= rank[x]*rank[y]

        if rank[x] < rank[y]:
            tree[x] = y
            rank[y] += rank[x]
        else:
            tree[y] = x
            rank[x] += rank[y]

print(("\n".join(reversed(list(main())))))
# Original solution
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]


n, m = map(int, input().split())
bridges = []
for _ in range(m):
    a, b = map(int, input().split())
    a -= 1
    b -= 1
    bridges.append((a, b))

uf = UnionFind(n)

incnv = (n - 1) * n // 2
ans = [None] * m

for i in range(m - 1, -1, -1):
    a, b = bridges[i]
    ans[i] = incnv
    if not uf.same(a, b):
        x = uf.size(a)
        incnv += x * (x - 1) // 2

        x = uf.size(b)
        incnv += x * (x - 1) // 2

        uf.unite(a, b)
        x = uf.size(a)
        incnv -= x * (x - 1) // 2

print(*ans, sep='\n')


# Optimized solution
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 main():
    import sys

    input = sys.stdin.readline

    n, m = map(int, input().split())

    g = tuple(reversed(tuple((int(x) - 1 for x in input().split()) for _ in range(m))))
    t = n * (n - 1) // 2

    ret = [t]  # 最後反転
    uf = UnionFind(n)
    for a, b in g[:-1]:
        if not uf.same(a, b):
            t -= uf.size(a) * uf.size(b)
        ret.append(t)
        uf.unite(a, b)
    ret.reverse()
    print(*ret, sep='\n')


if __name__ == '__main__':
    main()
# Original solution
class UnionFind:
    def __init__(self, n):
        self.v = [-1] * n

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

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return False
        else:
            if self.v[x] > self.v[y]:
                x, y = y, x
            self.v[x] += self.v[y]
            self.v[y] = x
            return True

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

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


def main():
    import sys
    input = sys.stdin.readline

    N, M = map(int, input().split())

    collapse_schedule = []
    for _ in range(M):
        A, B = (int(x) - 1 for x in input().split())
        collapse_schedule.append((A, B))
    collapse_schedule.reverse()

    uf = UnionFind(N)

    def evaluate(size):
        return size * (size - 1) // 2

    all_dropped = evaluate(N)
    curr = all_dropped

    ret = [-1] * M
    ret[-1] = all_dropped

    for i, (a, b) in zip(reversed(range(M - 1)), collapse_schedule):
        if not uf.same(a, b):
            sa, sb = uf.size(a), uf.size(b)
            ea, eb = evaluate(sa), evaluate(sb)

            curr += ea + eb

            uf.unite(a, b)

            sa = uf.size(a)
            ea = evaluate(sa)

            curr -= ea

        ret[i] = curr

    print(*ret, sep='\n')


if __name__ == '__main__':
    main()


# Optimized solution
class UnionFind:
    def __init__(self, n):
        self.v = [-1] * n

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

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return False
        else:
            if self.v[x] > self.v[y]:
                x, y = y, x
            self.v[x] += self.v[y]
            self.v[y] = x
            return True

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

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


def main():
    import sys
    input = sys.stdin.readline

    N, M = map(int, input().split())

    es = []
    for _ in range(M):
        a, b = (int(x) - 1 for x in input().split())
        es.append((a, b))
    es.reverse()
    es.pop()

    uf = UnionFind(N)
    ans = [N * (N - 1) // 2]
    t = ans[-1]
    for a, b in es:
        if not uf.same(a, b):
            t -= uf.size(a) * uf.size(b)
        ans.append(t)
        uf.unite(a, b)
    ans.reverse()

    print(*ans, sep='\n')


if __name__ == '__main__':
    main()
# Original solution
# coding: utf-8
import sys

sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

N, M = lr()
AB = [lr() for _ in range(M)]
V = [x for x in range(N+1)]
total = N * (N-1) // 2

def find(A, x):
    parent = A[x]
    if parent == x: return x
    root = find(A, parent)
    A[x] = root
    return root

def union(A, x, y):
    root, second = find(A, x), find(A, y)
    if root > second:
        second, root = root, second
    A[second] = root

conv = 0
answer = []
for a, b in AB[::-1]:
    answer.append(total - conv)
    root_A = find(V, a); root_B = find(V, b)
    if root_A != root_B:
        conv += V.count(root_A) * V.count(root_B)
        union(V, a, b)
        V = [find(V, x) for x in V]

for x in answer[::-1]:
    print(x)


# Optimized solution
# coding: utf-8
import sys

sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

N, M = lr()
AB = [lr() for _ in range(M)]
V = [x for x in range(N+1)]
total = N * (N-1) // 2

def find(A, x):
    parent = A[x]
    if parent == x: return x
    root = find(A, parent)
    A[x] = root
    return root

def union(A, x, y):
    root, second = find(A, x), find(A, y)
    if root > second:
        second, root = root, second
    A[second] = root

conv = 0
answer = []
group = [1] * (N+1)
for a, b in AB[::-1]:
    answer.append(total - conv)
    root_A = find(V, a); root_B = find(V, b)
    if root_A != root_B:
        conv += group[root_A] * group[root_B]
        group[root_A] += group[root_B]
        group[root_B] = group[root_A]
        union(V, a, b)

for x in answer[::-1]:
    print(x)
# Original solution
def comb(n):
    return (n * (n - 1)) // 2


def main():
    n, m = [int(a) for a in input().split()]

    AB = [
        [int(a) for a in input().split()]
        for _ in range(m)
    ]

    table = {i: (1, set([i])) for i in range(n)}  # (便利さ,行ける島集合)

    current_benrisa = 0
    max_hubensa = comb(n)

    reversed_benrisa = []
    for ai, bi in reversed(AB):
        reversed_benrisa.append(current_benrisa)
        s1_benrisa, s1_set = table[ai-1]
        s2_benrisa, s2_set = table[bi-1]
        if s1_set is s2_set:  # 変化なし
            continue

        new_benri = s1_benrisa + s2_benrisa
        new_set = s1_set.union(s2_set)
        for t in new_set:
            table[t] = (new_benri, new_set)

        inc = s1_benrisa * s2_benrisa
        current_benrisa += inc
        continue

    for a in reversed(reversed_benrisa):
        print((max_hubensa - a))


if __name__ == '__main__':
    main()


# Optimized solution
def comb(n):
    return (n * (n - 1)) // 2


def main():
    n, m = [int(a) for a in input().split()]

    AB = [
        [int(a) for a in input().split()]
        for _ in range(m)
    ]

    table = {i: {i} for i in range(n)}  # (便利さ,行ける島集合)

    current_benrisa = 0
    max_hubensa = comb(n)

    reversed_benrisa = []
    for ai, bi in reversed(AB):
        reversed_benrisa.append(current_benrisa)
        s1_set = table[ai - 1]
        s2_set = table[bi - 1]
        if s1_set is s2_set:  # 変化なし
            continue

        s1_benrisa = len(s1_set)
        s2_benrisa = len(s2_set)
        # new_benri = s1_benrisa + s2_benrisa
        if len(s1_set) > len(s2_set):
            s1_set.update(s2_set)
            for t in s2_set:
                table[t] = s1_set
        else:
            s2_set.update(s1_set)
            for t in s1_set:
                table[t] = s2_set

        # new_set = s1_set.union(s2_set)
        # for t in new_set:
        #     table[t] = (new_benri, new_set)

        inc = s1_benrisa * s2_benrisa
        current_benrisa += inc
        continue

    for a in reversed(reversed_benrisa):
        print((max_hubensa - a))


if __name__ == '__main__':
    main()