//#include "bits/stdc++.h"
#include <iostream>
#include <vector>
#include <map>
#include <utility>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <numeric>
#include <complex>
#include <bitset>
#include <functional>
#include <stack>
#include <regex>
#include <tuple>
#include <iomanip>

#define int long long
#define REP(i,l,r) REPEAT(i,l,r,true) // [l, r)
#define rep(i,n) REP(i,0,n)           // [0, n)
#define REPEAT(i,l,r,condition) for(int i=(condition)?l:r-1;(condition)?i<r:i>=l;(condition)?++i:--i) // false<-[l, r)->true
#define all(e) e.begin(),e.end()
#define rall(e) e.rbegin(),e.rend()
#define pb push_back
#define fs first
#define sc second
#define show(...) cerr<<#__VA_ARGS__<<" = ";_DEBUG(__VA_ARGS__)
#define showlr(n,l,r) cerr<<#n<<" = ";for(int i=l;i<r;i++){cerr<<n[i]<<", ";}cerr<<endl // [l, r)

#define YN(condition) puts((condition)?"YES":"NO")
#define Yn(condition) puts((condition)?"Yes":"No")
#define yn(condition) puts((condition)?"yes":"no")
#define YES puts("YES")
#define Yes puts("Yes")
#define yes puts("yes")
#define NO  puts("NO")
#define No  puts("No")
#define no  puts("no")

#define case(i) printf("Case #%lld: ",i)

using namespace std;

using vi=vector<int>;
using pint=pair<int,int>;

struct io{io(){cin.tie(0);ios::sync_with_stdio(false);cout.tie(0);cout<<fixed<<setprecision(20);}}io;

template<class T> istream& operator >>(istream &is, vector<T> &v){for(T &e:v)is>>e;return is;}
template<class T> ostream& operator <<(ostream &os, vector<T> v){os<<"{";for(T &e:v)os<<e<<(v.size()-(int)(&e-&v[0])>1?", ":"");os<<"}";return os;}

void _DEBUG(){}
template<typename H,typename... T> void _DEBUG(H a,T...b){cerr<<a<<(sizeof...(b)?",":"\n");_DEBUG(b...);}

inline void in(){}
template<typename H,typename... T>void in(H &a, T&... b){cin>>a;in(b...);}
inline void out(){}
template<typename H,typename... T> void out(H a, T... b){cout<<a<<(sizeof...(b)?" ":"\n");out(b...);}

template<class T> void resz(int n,T& v){v.resize(n);}
template<class H,class... T> void resz(int n,H& a,T&... b){a.resize(n);resz(n,b...);}

template<typename V,typename H> void resize(vector<V>& v,const H a){v.resize(a);}
template<typename V,typename H,typename... T> void resize(vector<V>& v,const H& a,const T... b){v.resize(a);for(auto &v:v) resize(v,b...);}

const int INF=1LL<<55;
const int MOD=1000000007;
const double EPS=1e-8;

class UnionFind {
public:
    /**
     * コンストラクタ．
     * @param n
     */
    UnionFind(int n);

    /**
     * 木の根を求める
     * @param x
     * @return
     */
    int find(int x);

    /**
     * xとyの属する集合を併合する
     * @param x
     * @param y
     */
    void unite(int x, int y);

    /**
     * xとyが同じ集合に属するか否か
     * @param x
     * @param y
     * @return
     */
    bool same(int x, int y);

    int size(int x);

private:
    std::vector<int> sz;
};

UnionFind::UnionFind(int n) {
    sz.assign(n, -1);
}

// 木の根を求める
int UnionFind::find(int x) {
    if (sz[x] < 0) return x;
    return sz[x] = find(sz[x]);
}

// xとyの属する集合を併合する
void UnionFind::unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;

    if (sz[x] < sz[y]) swap(x, y);
    sz[y] += sz[x];
    sz[x] = y;
}

// xとyが同じ集合に属するか否か
bool UnionFind::same(int x, int y) {
    return find(x) == find(y);
}

int UnionFind::size(int x) {
    return -sz[find(x)];
}

int N,M;
vi A,B;
vi res;

signed main(){

    in(N,M);
    int a,b;
    rep(i,M){
        in(a,b);
        a--;b--;
        A.pb(a),B.pb(b);
    }
    reverse(all(A));
    reverse(all(B));

    UnionFind uf(N);

    int s=(N-1)*N/2;
    rep(i,M){
        res.pb(s);
        if(uf.same(A[i],B[i])) continue;
        s-=uf.size(A[i])*uf.size(B[i]);
        uf.unite(A[i],B[i]);
    }
    reverse(all(res));
    for(auto e:res) out(e);

    return 0;
}


Measured memory_bytes: 4588