bzoj 3674 可持久化并查集加强版——可持久化并查集

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3674

用主席树维护 fa[ ]  和 siz[ ] 。改 fa[ ] 和改 siz[ ] 都是新建节点。

写成 rt[ i ] = rt[ i-1 ] ,因为跳到第 k 步之后的那个第 k 步不一定是一个 0 操作。

找 fa 就是在当前版本的主席树查很多次。可以路径压缩,就和改 fa[ ] 一样,覆盖当前版本。不过空间会很大(n*50都不行,n*70可以),而且还变慢了?

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return fx?ret:-ret;
}
const int N=2e5+5,M=N*70;
int n,m,rt[N],ans;
int tot,ls[M],rs[M],vl[M],siz[M];
void build(int l,int r,int cr)
{
  if(l==r){vl[cr]=l;siz[cr]=1;return;}
  int mid=l+r>>1;
  ls[cr]=++tot; build(l,mid,ls[cr]);
  rs[cr]=++tot; build(mid+1,r,rs[cr]);
}
void ins(int l,int r,int &cr,int pr,int p,int k)
{
  cr=++tot;ls[cr]=ls[pr];rs[cr]=rs[pr];
  if(l==r){vl[cr]=k;siz[cr]=siz[pr];return;}
  int mid=l+r>>1;
  if(p<=mid)ins(l,mid,ls[cr],ls[pr],p,k);
  else ins(mid+1,r,rs[cr],rs[pr],p,k);
}
void add(int l,int r,int &cr,int pr,int p,int k)
{
  cr=++tot;ls[cr]=ls[pr];rs[cr]=rs[pr];
  if(l==r){vl[cr]=vl[pr];siz[cr]=siz[pr]+k;return;}
  int mid=l+r>>1;
  if(p<=mid)add(l,mid,ls[cr],ls[pr],p,k);
  else add(mid+1,r,rs[cr],rs[pr],p,k);
}
int qry(int l,int r,int cr,int p)
{
  if(l==r)return cr; int mid=l+r>>1;//return cr not vl for qry siz
  if(p<=mid)return qry(l,mid,ls[cr],p);
  else return qry(mid+1,r,rs[cr],p);
}
int fnd(int nw,int a)
{
  int fa=qry(1,n,nw,a);
  if(a==vl[fa])return fa; fa=fnd(nw,vl[fa]);
  ins(1,n,nw,nw,a,vl[fa]);//fa[a]=fnd(fa[a])
  return fa;
}
int main()
{
  n=rdn();m=rdn();
  rt[0]=tot=1;build(1,n,rt[0]);
  for(int i=1,op,u,v;i<=m;i++)
    {
      op=rdn();
      if(op==1)
    {
      rt[i]=rt[i-1]; u=rdn();v=rdn();
      u=fnd(rt[i],u^ans); v=fnd(rt[i],v^ans);
      if(vl[u]==vl[v])continue;
      if(siz[u]>siz[v])swap(u,v);
      u=vl[u];v=vl[v]; ins(1,n,rt[i],rt[i],u,v);
      add(1,n,rt[i],rt[i],v,siz[u]);
    }
      else if(op==2){ u=rdn()^ans; rt[i]=rt[u];}
      else
    {
      rt[i]=rt[i-1]; u=rdn();v=rdn();
      u=vl[fnd(rt[i],u^ans)]; v=vl[fnd(rt[i],v^ans)];
      ans=(u==v); printf("%d\n",ans);
    }
    }
  return 0;
}

 

posted on 2019-02-15 11:13  Narh  阅读(147)  评论(0编辑  收藏  举报

导航