• 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
    ",ans);
        }
        }
      return 0;
    }
  • 相关阅读:
    re模块详解
    PythonS12-day4学习笔记
    Python-day3作业-haproxy配置文件管理脚本
    Python——Day3知识点——文件操作
    Python-Day3知识点——深浅拷贝、函数基本定义、内置函数
    collections系列
    set集合
    服务器三大体系SMP、NUMA、MPP介绍
    CPU指令集
    PS与TOP详解
  • 原文地址:https://www.cnblogs.com/Narh/p/10382528.html
Copyright © 2020-2023  润新知