题解
将     x坐标相同的点连接到一起,将     y坐标相同的点连接到一起,每个联通块的     x、y坐标的种类的乘积的和就是答案。
 对于第     i个联通块(集合),用     nx[i]表示其中     x坐标的种类数,     ny[i]表示其中     y坐标的种类数,     nx[i]∗ny[i]就是这个集合的贡献
 我们将     x、y坐标当做点,当一个新点加入时,将     x[i]与     y[i]合并,同时修改这个集合的     nx和     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]);
}

京公网安备 11010502036488号