/*
可持久化线段树+启发式合并.(引自yjy)
可持久化线段树维护当前状态下集合的关系和秩的信息.
所谓的秩就是以该元素为代表元的所有元素中的最大深度.
然后按秩合并的目的是为了降常.
每个叶节点维护一颗线段树
合并的时候在权值线段树的子节点加一个数,
相当于连了一条边 表示有关系存在.
要先查询要将合并两个元素的父亲所在位置.
显然只有在两个集合秩相同时才更新秩.
*/
#include<cstdio>
#include<iostream>
using namespace std;
const int N=2e5+5,Z=N*20;
int n,m;
int sz,root[N],ls[Z],rs[Z],dep[Z],fax[Z];
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void build(int &k,int l,int r){
k=++sz;
if(l==r){
fax[k]=l;return ;
}
int mid=l+r>>1;
build(ls[k],l,mid);
build(rs[k],mid+1,r);
}
int find_pos(int &k,int l,int r,int x){
if(l==r) return k;
int mid=l+r>>1;
if(x<=mid) return find_pos(ls[k],l,mid,x);
else return find_pos(rs[k],mid+1,r,x);
}
int get_fa(int &k,int x){//非路径压缩
int p=find_pos(k,1,n,x);
if(fax[p]==x) return p;
else return get_fa(k,fax[p]);
}
void insert(int &k,int last,int l,int r,int x,int y){
k=++sz;
if(l==r){fax[k]=y;dep[k]=dep[last];return ;}
ls[k]=ls[last];
rs[k]=rs[last];
int mid=l+r>>1;
if(x<=mid) insert(ls[k],ls[last],l,mid,x,y);
else insert(rs[k],rs[last],mid+1,r,x,y);
}
void update(int &k,int l,int r,int v){
if(l==r){dep[k]++;return ;}
int mid=l+r>>1;
if(v<=mid) update(ls[k],l,mid,v);
else update(rs[k],mid+1,r,v);
}
void merge(int l1,int l2,int i){
if(dep[l1]>dep[l2]) swap(l1,l2);
insert(root[i],root[i-1],1,n,fax[l1],fax[l2]);
if(dep[l1]==dep[l2]) update(root[i],1,n,fax[l2]);
}
int main(){
freopen("bzoj_3974.in","r",stdin);
freopen("bzoj_3974.out","w",stdout);
n=read();m=read();
build(root[0],1,n);
for(int i=1,opt,x,y,l1,l2,ans=0;i<=m;i++){
opt=read();x=read()^ans;if(opt&1) y=read()^ans;
root[i]=root[opt&1?i-1:x];
if(opt==1){
l1=get_fa(root[i],x);
l2=get_fa(root[i],y);
if(l1!=l2) merge(l1,l2,i);
}
if(opt==3){
l1=get_fa(root[i],x);
l2=get_fa(root[i],y);
ans=(l1==l2);
printf("%d\n",ans);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术