【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;
}
}
}
}