【BZOJ 4668 冷战】

题目:

【BZOJ 4668 冷战】

思路:

因为考虑强制在线,我们是肯定要维护形状的
我们发现如果\((u,v)\)这条边如果\(u,v\)已经连上,那么对于最终答案这条边是没有贡献的
所以我们发现其实我们最后要维护的是一棵树
因为没有拆边操作,我们用并查集维护就好了
然后计点权\(p(u)\)\(u与fa(u)\)连上的时间
查询时查询\(p(lca(u,v))\)就可以了

代码

// code by Dix_
#include<bits/stdc++.h>
#define ll long long

inline ll read(){
    char C=getchar();
    ll N=0 , F=1;
    while(('0' > C || C > '9') && (C != '-')) C=getchar();
    if(C == '-') F=-1 , C=getchar();
    while('0' <= C && C <= '9') N=(N << 1)+(N << 3)+(C - 48) , C=getchar();
    return F*N;
}

ll n,m;
ll last = 0;
ll fa[1000010],rank[1000010],dep[1000010],v[1000010];

void init(){
	for(int i = 1;i <= n;++i)
	fa[i] = i,rank[i] = 1,dep[i] = 0;
}

int find(ll now){
	ll ans = now;
	if(now == fa[now])
	return now;
	if(now != fa[now])
	ans = find(fa[now]);
	dep[now] = dep[fa[now]] + 1;
	return ans;
}

int lca(ll x,ll y){
	int ans = 0;
	while(x != y){
		if(dep[x] < dep[y])std::swap(x,y);
		ans = std::max((ll)ans,v[x]);
		x = fa[x];
	}
	return ans;
}

ll t = 0;

int main(){
	scanf("%lld%lld",&n,&m);
	init();
	for(int i = 1;i <= m;++i){
		ll op,x,y;
		scanf("%lld%lld%lld",&op,&x,&y);
		x ^= last,y ^= last;
		ll fx = find(x),fy = find(y);
		if(op == 0){
			t ++ ;
			if(rank[fx] >= rank[fy]){
				fa[fy] = fx;
				v[fy] = t;
				if(rank[fx] == rank[fy]) rank[fx] ++ ;
			}
			else{
				fa[fx] = fy;
				v[fx] = t;
			}
		}
		if(op == 1){
			if(fx != fy){
				std::cout<<0<<std::endl;
				last = 0;
			}else{
			last = lca(x,y);
			std::cout<<last<<std::endl;
			}
		}
	}
}



原文地址:https://www.cnblogs.com/dixiao/p/14445860.html