#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#include <map>

#ifndef U_L_LONG
typedef unsigned long long ULLONG;
#endif
#ifndef L_LONG
typedef long long LLONG;
#endif
template <class _T> static _T tp_abs(const _T& a) {
	//	usage:  tp_abs<type name>(a);
	return ((a < 0) ? (a * -1) : a);
}
template <class _T> static _T tp_min(_T a, _T b) {
	return a < b ? a : b;
}
template <class _T> static _T tp_max(_T a, _T b) {
	return a > b ? a : b;
}
template<class _T> static void get1int(_T& a) {
	const char* fmt = " %d";
	if (sizeof(_T) == sizeof(long long)) {
		fmt = " %lld";
	}

	if (scanf(fmt, &a) < 0) {
		printf("g1int Error\n");
	}
}
template<class _T> static void get2int(_T& a, _T& b) {
	const char* fmt = " %d %d";
	if (sizeof(_T) == sizeof(long long)) {
		fmt = " %lld %lld";
	}

	if (scanf(fmt, &a, &b) < 0) {
		printf("g2int Error\n");
	}
}
template<class _T> static void get3int(_T& a, _T& b, _T& c) {
	const char* fmt = " %d %d %d";
	if (sizeof(_T) == sizeof(long long)) {
		fmt = " %lld %lld %lld";
	}

	if (scanf(fmt, &a, &b, &c) < 0) {
		printf("g3int Error\n");
	}
}
template <class _T> static void tp_swap(_T& right, _T& left) {
	//	usage:  tp_swap<type name>(a, b);
	_T tmp = right;
	right = left;
	left = tmp;
}
static void getstring(char* buff) {
	if (scanf(" %s", buff) < 0) {
		printf("getstr error!\n");
	}
}

typedef std::pair<int, int> IntPair;


static void ABC120D_DecayedBridges();


#if 1
int main()
{
	ABC120D_DecayedBridges();
	fflush(stdout);
	return 0;
}
#endif


class ABC120D_edge {
public:
	int _edge1 = 0;
	int _edge2 = 0;
};

class tmUnionFindTree
{
protected:
	int* _par = 0;
	int* _rank = 0;
	int* _count = 0;

	void init(int size) {
		_par = new int[size];		//	親ノード
		_rank = new int[size];		//	高さ
		_count = new int[size];		//	結合グループの要素数

		for (int i = 0; i < size; i++) {
			_par[i] = i;
			_rank[i] = 0;
			_count[i] = 1;
		}
	}

public:
	tmUnionFindTree(int size = 10) {
		init(size);
	}

	~tmUnionFindTree() {
		delete[] _par;
		delete[] _rank;
		delete[] _count;
	}

	//	木の根を求める
	int find(int x) {
		if (_par[x] == x) {
			return x;
		}
		else {
			return(_par[x] = find(_par[x]));
		}
	}

	//	x と y の属する集合を併合
	void Unite(int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) {
			//	すでに同じ集合だった
			return;
		}

		if (_rank[x] < _rank[y]) {
			//	数をまず加算しておく
			_count[y] = _count[y] + _count[x];
			_par[x] = y;
		}
		else {
			//	数をまず加算しておく
			_count[x] = _count[y] + _count[x];

			_par[y] = x;
			if (_rank[x] == _rank[y]) {
				_rank[x]++;
			}
		}
	}

	bool IsUnion(int x, int y) {
		return (find(x) == find(y));
	}

	int count(int x) {
		return _count[find(x)];
	}
};

static void ABC120D_DecayedBridges()
{
	LLONG N, M;
	get2int<LLONG>(N, M);

	auto edge = new ABC120D_edge[M];
	auto ans = new LLONG[M + 1];
	for (int i = 0; i < M; i++) {
		get2int(edge[i]._edge1, edge[i]._edge2);
	}

	ans[M] = (N * (N - 1)) / 2;
	tmUnionFindTree uft(N);
	for (int i = M - 1; i >= 0; i--) {
		int edge1 = edge[i]._edge1 - 1;
		int edge2 = edge[i]._edge2 - 1;
		
		if (uft.IsUnion(edge1, edge2)) {
			ans[i] = ans[i + 1];
		}
		else {
			LLONG grp1 = uft.count(edge1);
			LLONG grp2 = uft.count(edge2);

			ans[i] = ans[i + 1] - (grp1 * grp2);
			uft.Unite(edge1, edge2);
		}
	}

	for (int i = 1; i <= M; i++) {
		printf("%lld\n", ans[i]);
	}

	delete[] edge;
	delete[] ans;
}


Measured memory_bytes: 4096