记录编号 529139 评测结果 AAAAAAAAAA
题目名称 [BZOJ 3674] 可持久化并查集加强版 最终得分 100
用户昵称 GravatarLGLJ 是否通过 通过
代码语言 C++ 运行时间 0.654 s
提交时间 2019-03-28 15:08:22 内存使用 38.98 MiB
显示代码纯文本
#include <iostream>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#define I inline
#define R register
using namespace std;
const int maxn=2*1e5+10;
int n,m;
struct TREE
{
	int l,r,fa,deep;
}tree[maxn*20];
int zxt[maxn]={0},tot=0;
int lastans=0;
I int read()
{
	int x=0;
	char ch=0;
	bool w=true;
	while(!isdigit(ch)){if(ch=='-')w=false;ch=getchar();}
	while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return w?x:-x;
}
I void build(int &rt,int le,int ri)
{
	rt=++tot;
	if(le==ri)
	{
		tree[rt].fa=le;
		tree[rt].deep=1;
		return ;
	}
	int mid=(le+ri)>>1;
	build(tree[rt].l,le,mid);
	build(tree[rt].r,mid+1,ri);
}
I void join(int &rt,int le,int ri,int pre,int x,int y)
{
	rt=++tot;
	tree[rt].l=tree[pre].l;
	tree[rt].r=tree[pre].r;//只有叶子节点对应的是各个集合,其他点的fa,deep没必要更新
	if(le==ri)
	{
		tree[rt].fa=y;
		tree[rt].deep=tree[pre].deep;
		return ;
	}
	int mid=(le+ri)>>1;
	if(x<=mid)
		join(tree[rt].l,le,mid,tree[pre].l,x,y);
	else
		join(tree[rt].r,mid+1,ri,tree[pre].r,x,y);
}
I void update(int rt,int le,int ri,int x)
{
	if(le==ri)
	{
		++tree[rt].deep;
		return ;
	}
	int mid=(le+ri)>>1;
	if(x<=mid)
		update(tree[rt].l,le,mid,x);
	else
		update(tree[rt].r,mid+1,ri,x);
}
I int query(int rt,int le,int ri,int x)//返回主席树中的位置
{
	if(le==ri)
		return rt;//找到x在主席树中对应的位置
	int mid=(le+ri)>>1;
	if(x<=mid)
		return query(tree[rt].l,le,mid,x);
	else
		return query(tree[rt].r,mid+1,ri,x);
}
I int find(int rt,int x)
{
	int now=query(rt,1,n,x);//找到主席树中对应的那个点所在位置
	return tree[now].fa==x?now:find(rt,tree[now].fa);
}
I int MAIN()
{
	freopen ("bzoj_3974.in","r",stdin);
	freopen ("bzoj_3974.out","w",stdout);
	n=read(),m=read();
	build(zxt[0],1,n);
	for(R int i=1,a,b,c;i<=m;++i)
	{
		a=read(),b=read();
		switch(a)
		{
			case 1:
			{
				c=read();
				b^=lastans,c^=lastans;
				zxt[i]=zxt[i-1];//先将整个树平移过来
				int x=find(zxt[i],b),y=find(zxt[i],c);
				if(tree[x].fa!=tree[y].fa)//判断是否就在一个集合里
				{
					if(tree[x].deep>tree[y].deep)//x的深度要<y
						swap(x,y);
					join(zxt[i],1,n,zxt[i-1],tree[x].fa,tree[y].fa);//合并
					if(tree[x].deep==tree[y].deep)
						update(zxt[i],1,n,tree[y].fa);
				}
				break;
			}
			case 2:
			{
				b^=lastans;
				zxt[i]=zxt[b];//回到原先状态
				break;
			}
			default:
			{
				c=read();
				b^=lastans,c^=lastans;
				zxt[i]=zxt[i-1];
				int x=find(zxt[i],b),y=find(zxt[i],c);
				if(tree[x].fa==tree[y].fa)
					lastans=1;
				else
					lastans=0;
				printf("%d\n",lastans);
			}
		}
	}
	return 0;
}
int lglj=MAIN();
int main(){;}