Language: C++

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <algorithm>
#include <map>
#include <utility>
#include <vector>
using namespace std;
#define mp  std::make_pair
#define ll long long int
#define abs(n) ((n>0)?(n):((n)*(-1)))
#define CEIL(a,b) (((a) + ((b)-1)) / (b))
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define REP(i,n) FOR(i,0,(n)-1)
#define VREP_ll(v) for(std::vector<ll>::iterator itr = (v).begin(); itr != (v).end();itr++)
#define VREP_int(v) for(std::vector<int>::iterator itr = (v).begin(); itr != (v).end();itr++)
#define VALL(v) ((v).begin(),(v).end())
#define errln(v) cerr << (v) << endl;
#define println(v) cout << (v) << endl;


struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
    map<int,int> parcnts;
    int N;

    UnionFind(int _N) : par(_N) { //最初は全てが根であるとして初期化
        for(int i = 0; i < _N; i++) par[i] = i;
        N = _N;
    }

    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }

    void unite(int x, int y) { // xとyの木を併合
    	int rxcnt,rycnt;
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
        if(parcnts.find(rx)==parcnts.end()){
        	rxcnt = 1;
        }else{
        	rxcnt = parcnts.find(rx)->second;
        	parcnts.erase(rx);
        }
        if(parcnts.find(ry)!=parcnts.end()){
        	parcnts.find(ry)->second += rxcnt;
        }else{
        	parcnts.insert(mp<int,int>(ry,1+rxcnt));
        }
    }

    ll calc(){
    	ll ret = N*(N-1)/2;
//    	errln(N);
    	for(auto i = parcnts.begin();
    			i != parcnts.end();
    			i++){
//    		cerr << i->first << " " << i-> second << endl;
    		int v = i->second;
    		ret -= v*(v-1)/2;
    	}
    	return ret;
    }

    void dump(){
    	REP(i,N){
    		cerr << par[i] << " ";
    	}
    	cerr << endl;
    }

    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }
};

int main(int argc, const char * argv[]) {
	ll n,m;
	cin >> n >> m;
	int a[m],b[m];
	ll ret[m+1];

	REP(i,m){
		cin >> a[i] >> b[i];
	}

	UnionFind tree(n);

	ret[m] = n*(n-1)/2;
	for(int i=m-1;i>=0;i--){
		tree.unite(a[i]-1,b[i]-1);
//		tree.dump();
		ret[i] = tree.calc();
	}

	FOR(i,1,m){
		println(ret[i]);
	}

	return 0;
}


Compiler output:
a.cc: In member function 'void UnionFind::unite(int, int)':
a.cc:53:44: error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'
   53 |                 parcnts.insert(mp<int,int>(ry,1+rxcnt));
      |                                            ^~
In file included from /usr/include/c++/14/bits/stl_algobase.h:64,
                 from /usr/include/c++/14/string:51,
                 from /usr/include/c++/14/bits/locale_classes.h:40,
                 from /usr/include/c++/14/bits/ios_base.h:41,
                 from /usr/include/c++/14/ios:44,
                 from /usr/include/c++/14/ostream:40,
                 from /usr/include/c++/14/iostream:41,
                 from a.cc:1:
/usr/include/c++/14/bits/stl_pair.h:1132:21: note:   initializing argument 1 of 'constexpr std::pair<typename std::__strip_reference_wrapper<typename std::decay<_Tp>::type>::__type, typename std::__strip_reference_wrapper<typename std::decay<_Tp2>::type>::__type> std::make_pair(_T1&&, _T2&&) [with _T1 = int; _T2 = int; typename __strip_reference_wrapper<typename decay<_Tp>::type>::__type = int; typename decay<_Tp>::type = int; typename __strip_reference_wrapper<typename decay<_Tp2>::type>::__type = int; typename decay<_Tp2>::type = int]'
 1132 |     make_pair(_T1&& __x, _T2&& __y)
      |               ~~~~~~^~~