
class UnionFind:
    def __init__(self, N):
        self.parents = [i for i in range(N)]
        self.sizes = [1 for _ in range(N)]
        
    # 木の根をまとめる, 頂点 v が属するグループ番号を得る (O(α(n)))
    def root(self, x):
        if self.parents[x] == x:
            return x # 根
        else:
            self.parents[x] = self.root(self.parents[x]) # 経路圧縮
            return self.parents[x]
            
    # xとyが同じ集合に属するか否か
    def is_same(self, x, y):
        return self.root(x) == self.root(y)
        
    # xとyの属する集合を併合, 頂点 u が属するグループと頂点 v が属するグループを併合し、同じグループにする (O(α(n)))
    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.sizes[x] < self.sizes[y]:
            x, y = y, x
        self.sizes[x] += self.sizes[y]
        self.parents[y] = x
        return True
    
    # 頂点 v が属するグループと同じグループに属する頂点数を得る (O(1))
    def size(self, x):
        return self.sizes[self.root(x)]
        
        
        
N, M = map(int, input().split())

tree = UnionFind(N)

AB = []
for _ in range(M):
    a, b = map(int, input().split())
    AB.append([a, b])

AB = AB[::-1]

tree = UnionFind(N)
ans = [N*(N-1)//2]
for i in range(M):
    a, b = AB[i]
    a, b = tree.root(a-1), tree.root(b-1)
    if a != b:
        ans.append(ans[-1] - tree.size(a)*tree.size(b))
    else:
        ans.append(ans[-1])
    tree.unite(a, b)

ans = ans[:M][::-1]
for i in range(M):
    print(ans[i]) class UnionFind:
    def __init__(self, N):
        self.parents = [i for i in range(N)]
        self.sizes = [1 for _ in range(N)]
        
    # 木の根をまとめる, 頂点 v が属するグループ番号を得る (O(α(n)))
    def root(self, x):
        if self.parents[x] == x:
            return x # 根
        else:
            self.parents[x] = self.root(self.parents[x]) # 経路圧縮
            return self.parents[x]
            
    # xとyが同じ集合に属するか否か
    def is_same(self, x, y):
        return self.root(x) == self.root(y)
        
    # xとyの属する集合を併合, 頂点 u が属するグループと頂点 v が属するグループを併合し、同じグループにする (O(α(n)))
    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.sizes[x] < self.sizes[y]:
            x, y = y, x
        self.sizes[x] += self.sizes[y]
        self.parents[y] = x
        return True
    
    # 頂点 v が属するグループと同じグループに属する頂点数を得る (O(1))
    def size(self, x):
        return self.sizes[self.root(x)]
        
        
         UnionFind def __init__(self, N):
        self.parents = [i for i in range(N)]
        self.sizes = [1 for _ in range(N)]
        
    # 木の根をまとめる, 頂点 v が属するグループ番号を得る (O(α(n)))
     __init__ i for i in range(N) for i in range(N) i range(N) range N for i in range(N) i self.parents = [i for i in range(N)] self.parents self parents [i for i in range(N)] 1 for _ in range(N) for _ in range(N) _ range(N) range N for _ in range(N) 1 self.sizes = [1 for _ in range(N)] self.sizes self sizes [1 for _ in range(N)] self self N N def root(self, x):
        if self.parents[x] == x:
            return x # 根
        else:
            self.parents[x] = self.root(self.parents[x]) # 経路圧縮
            return self.parents[x]
            
    # xとyが同じ集合に属するか否か
     root if self.parents[x] == x:
            return x # 根
        else:
            self.parents[x] = self.root(self.parents[x]) # 経路圧縮
            return self.parents[x]
            
    # xとyが同じ集合に属するか否か
     self.parents[x] == x self.parents[x] self.parents self parents x x return x x self.parents[x] = self.root(self.parents[x]) self.parents[x] self.parents self parents x self.root(self.parents[x]) self.root self root self.parents[x] self.parents self parents x return self.parents[x] self.parents[x] self.parents self parents x self self x x def is_same(self, x, y):
        return self.root(x) == self.root(y)
        
    # xとyの属する集合を併合, 頂点 u が属するグループと頂点 v が属するグループを併合し、同じグループにする (O(α(n)))
     is_same return self.root(x) == self.root(y) self.root(x) == self.root(y) self.root(x) self.root self root x self.root(y) self.root self root y self self x x y y def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.sizes[x] < self.sizes[y]:
            x, y = y, x
        self.sizes[x] += self.sizes[y]
        self.parents[y] = x
        return True
    
    # 頂点 v が属するグループと同じグループに属する頂点数を得る (O(1))
     unite x = self.root(x) x self.root(x) self.root self root x y = self.root(y) y self.root(y) self.root self root y if x == y:
            return False
         x == y x y return False False if self.sizes[x] < self.sizes[y]:
            x, y = y, x
         self.sizes[x] < self.sizes[y] self.sizes[x] self.sizes self sizes x self.sizes[y] self.sizes self sizes y x, y = y, x x y y x self.sizes[x] += self.sizes[y] self.sizes[x] self.sizes self sizes x self.sizes[y] self.sizes self sizes y self.parents[y] = x self.parents[y] self.parents self parents y x return True True self self x x y y def size(self, x):
        return self.sizes[self.root(x)]
        
        
         size return self.sizes[self.root(x)] self.sizes[self.root(x)] self.sizes self sizes self.root(x) self.root self 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 tree = UnionFind(N) tree UnionFind(N) UnionFind N AB = [] AB [] for _ in range(M):
    a, b = map(int, input().split())
    AB.append([a, b]) _ range(M) range M a, b = map(int, input().split()) a map(int, input().split()) map int input().split() ().split () input split b AB.append([a, b]) AB.append AB append [a, b] a b AB = AB[::-1] AB AB[::-1] AB ::-1 -1 tree = UnionFind(N) tree UnionFind(N) UnionFind N ans = [N*(N-1)//2] ans [N*(N-1)//2] N*(N-1)//2 N*(N-1) N N-1 N 1 2 for i in range(M):
    a, b = AB[i]
    a, b = tree.root(a-1), tree.root(b-1)
    if a != b:
        ans.append(ans[-1] - tree.size(a)*tree.size(b))
    else:
        ans.append(ans[-1])
    tree.unite(a, b) i range(M) range M a, b = AB[i] a AB[i] AB i b a, b = tree.root(a-1), tree.root(b-1) a tree.root(a-1) tree.root tree root a-1 a 1 b tree.root(b-1) tree.root tree root b-1 b 1 if a != b:
        ans.append(ans[-1] - tree.size(a)*tree.size(b))
    else:
        ans.append(ans[-1])
     a != b a b ans.append(ans[-1] - tree.size(a)*tree.size(b)) ans.append ans append ans[-1] - tree.size(a)*tree.size(b) ans[-1] ans -1 tree.size(a)*tree.size(b) tree.size(a) tree.size tree size a tree.size(b) tree.size tree size b ans.append(ans[-1]) ans.append ans append ans[-1] ans -1 tree.unite(a, b) tree.unite tree unite a b ans = ans[:M][::-1] ans ans[:M][::-1] [:M] ans :M M ::-1 -1 for i in range(M):
    print(ans[i]) i range(M) range M print(ans[i]) print ans[i] ans i b = tree.root(a-1), tree.root(b-1) tree.root(b-1) b class UnionFind:
    def __init__(self, N):
        self.parents = [i for i in range(N)]
        self.sizes = [1 for _ in range(N)]
        
    # 木の根をまとめる, 頂点 v が属するグループ番号を得る (O(α(n)))
    def root(self, x):
        if self.parents[x] == x:
            return x # 根
        else:
            self.parents[x] = self.root(self.parents[x]) # 経路圧縮
            return self.parents[x]
            
    # xとyが同じ集合に属するか否か
    def is_same(self, x, y):
        return self.root(x) == self.root(y)
        
    # xとyの属する集合を併合, 頂点 u が属するグループと頂点 v が属するグループを併合し、同じグループにする (O(α(n)))
    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.sizes[x] < self.sizes[y]:
            x, y = y, x
        self.sizes[x] += self.sizes[y]
        self.parents[y] = x
        return True
    
    # 頂点 v が属するグループと同じグループに属する頂点数を得る (O(1))
    def size(self, x):
        return self.sizes[self.root(x)]
        
        
         class UnionFind:
    def __init__(self, N):
        self.parents = [i for i in range(N)]
        self.sizes = [1 for _ in range(N)]
        
    # 木の根をまとめる, 頂点 v が属するグループ番号を得る (O(α(n)))
    def root(self, x):
        if self.parents[x] == x:
            return x # 根
        else:
            self.parents[x] = self.root(self.parents[x]) # 経路圧縮
            return self.parents[x]
            
    # xとyが同じ集合に属するか否か
    def is_same(self, x, y):
        return self.root(x) == self.root(y)
        
    # xとyの属する集合を併合, 頂点 u が属するグループと頂点 v が属するグループを併合し、同じグループにする (O(α(n)))
    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.sizes[x] < self.sizes[y]:
            x, y = y, x
        self.sizes[x] += self.sizes[y]
        self.parents[y] = x
        return True
    
    # 頂点 v が属するグループと同じグループに属する頂点数を得る (O(1))
    def size(self, x):
        return self.sizes[self.root(x)]
        
        
         UnionFind tree = UnionFind(N) UnionFind(N) tree AB = [] [] AB AB = AB[::-1] AB[::-1] AB ans = ans[:M][::-1] ans[:M][::-1] ans ans = [N*(N-1)//2] [N*(N-1)//2] ans b = AB[i] AB[i] b tree = UnionFind(N) UnionFind(N) tree a, b = AB[i] AB[i] a b = map(int, input().split()) map(int, input().split()) b a, b = tree.root(a-1), tree.root(b-1) tree.root(a-1) a N, M = map(int, input().split()) map(int, input().split()) N M = map(int, input().split()) map(int, input().split()) M a, b = map(int, input().split()) map(int, input().split()) a

class UnionFind:
    def __init__(self, N):
        self.parents = [i for i in range(N)]
        self.sizes = [1 for _ in range(N)]
        
    # 木の根をまとめる, 頂点 v が属するグループ番号を得る (O(α(n)))
    def root(self, x):
        if self.parents[x] == x:
            return x # 根
        else:
            self.parents[x] = self.root(self.parents[x]) # 経路圧縮
            return self.parents[x]
            
    # xとyが同じ集合に属するか否か
    def is_same(self, x, y):
        return self.root(x) == self.root(y)
        
    # xとyの属する集合を併合, 頂点 u が属するグループと頂点 v が属するグループを併合し、同じグループにする (O(α(n)))
    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
        if self.sizes[x] < self.sizes[y]:
            x, y = y, x
        self.sizes[x] += self.sizes[y]
        self.parents[y] = x
        return True
    
    # 頂点 v が属するグループと同じグループに属する頂点数を得る (O(1))
    def size(self, x):
        return self.sizes[self.root(x)]
        
        
        
N, M = map(int, input().split())

tree = UnionFind(N)

AB = []
for _ in range(M):
    a, b = map(int, input().split())
    AB.append([a, b])

AB = AB[::-1]

tree = UnionFind(N)
ans = [N*(N-1)//2]
for i in range(M):
    a, b = AB[i]
    a, b = tree.root(a-1), tree.root(b-1)
    if a != b:
        ans.append(ans[-1] - tree.size(a)*tree.size(b))
    else:
        ans.append(ans[-1])
    tree.unite(a, b)

ans = ans[:M][::-1]
for i in range(M):
    print(ans[i])