题解

x x x坐标相同的点连接到一起,将 y y y坐标相同的点连接到一起,每个联通块的 x y x、y xy坐标的种类的乘积的和就是答案。
对于第 i i i个联通块(集合),用 n x [ i ] nx[i] nx[i]表示其中 x x x坐标的种类数, n y [ i ] ny[i] ny[i]表示其中 y y y坐标的种类数, n x [ i ] n y [ i ] nx[i]*ny[i] nx[i]ny[i]就是这个集合的贡献
我们将 x y x、y xy坐标当做点,当一个新点加入时,将 x [ i ] x[i] x[i] y [ i ] y[i] y[i]合并,同时修改这个集合的 n x nx nx n y ny ny的大小,如下图

这里将点抽象成为一种连接两点的父子关系。点的加入意味着两个集合的合并。我们在合并时就可以更新答案。
但是,这道题涉及点的消失的问题,就意味着之前建立的关系可能需要回滚。
这里,我们以时间轴建立线段树,统计出每一个点在图上出现的时间段,插入到线段树中。
在线段树中,往下层走,意味着新的点的加入,向上层走,就进行回滚操作。如果左右边界相等,就意味着到一个独立的时间点了,这一时间的答案就知道了。

代码

#include<bits/stdc++.h>
#define N 600010
#define INF 0x3f3f3f3f
#define eps 1e-10
// #define pi 3.141592653589793
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/priority_queue.hpp>
using namespace __gnu_pbds;
typedef pair<int,int> pi;
typedef pair<int,pi> pp;
typedef __gnu_pbds::priority_queue<pp,greater<pp> > heap;

map<pi,int> mp;
vector<pi> a[N<<1];
LL nx[N],ny[N],sz[N],ans[N],fa[N],res;
pi st[N];
int op=0;
int getfa(int x){
	return(fa[x]==x?x:getfa(fa[x]));
}

void ins(int x,int fl,int fr,int l,int r,pi t){
	if (l==fl && fr==r) a[x].pb(t);else
	{
		int mid=l+r>>1;
		if (fr<=mid) ins(x<<1,fl,fr,l,mid,t);else
		if (fl>mid) ins(x<<1|1,fl,fr,mid+1,r,t);else{
			ins(x<<1,fl,mid,l,mid,t);
			ins(x<<1|1,mid+1,fr,mid+1,r,t);
		}
	}
}

void spy(int x,int l,int r){
	int tm=op;
	for (auto i:a[x]){
		int x=getfa(i.fi),y=getfa(i.se);
		if (x!=y){
			if (sz[x]<sz[y]) swap(x,y);
			st[++op]=pi(x,y);
			fa[y]=x;
			res-=nx[x]*ny[x]+nx[y]*ny[y];
			sz[x]+=sz[y]; nx[x]+=nx[y]; ny[x]+=ny[y];
			res+=nx[x]*ny[x];
		}
	}
	if (l==r) ans[l]=res;else{
		spy(x<<1,l,l+r>>1);
		spy(x<<1|1,(l+r>>1)+1,r);
	}
	while(tm!=op){
		int x=st[op].fi,y=st[op--].se;
		res-=nx[x]*ny[x];
		sz[x]-=sz[y]; nx[x]-=nx[y]; ny[x]-=ny[y];
		res+=nx[x]*ny[x]+nx[y]*ny[y];
		fa[y]=y;
	}
}

int main()
{
	int n;
	sc(n);
	for (int i=1,x,y;i<=n;i++){
		scc(x,y); y+=3e5;
		if(mp[pi(x,y)]){
			ins(1,mp[pi(x,y)],i-1,1,n,pi(x,y));
			mp.erase(pi(x,y));
		}else mp[pi(x,y)]=i;
	}
	for (auto i:mp) ins(1,i.se,n,1,n,i.fi);
	for (int i=1;i<=6e5;i++) (i<=3e5?nx:ny)[i]=sz[i]=1,fa[i]=i;
	spy(1,1,n);
	printf("%lld",ans[1]);
	for (int i=2;i<=n;i++) printf(" %lld",ans[i]);
}