bzoj3674: 可持久化并查集加强版

Description:
自从zkysb出了可持久化并查集后……
hzwer:乱写能AC,暴力踩标程
KuribohG:我不路径压缩就过了!
ndsf:暴力就可以轻松虐!
zky:……

n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
请注意本题采用强制在线,所给的a,b,k均经过加密,加密方法为x = x xor lastans,lastans的初始值为0
0<n,m<=2*10^5


Input

 

Output

 

Sample Input

5 6
1 1 2
3 1 2
2 1
3 0 3
2 1
3 1 2

Sample Output

1
0
1
这里用到了主席树的一个性质:支持历史版本的操作,我们用主席树在每个点上表示它的祖先,感觉有点浪费,反正瞎搞就过了
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;

int bh, n, tn, m, l, r, G, a, b, cases;
int root[200010];
int Hash[200010];
struct NODe{
      int lson, rson, val;
}tree[200010 * 100];

void build(int &u,int l, int r) {
     u=bh++;
      if(l==r) 
    {
        tree[u].val=0;
        return;
      }
      int mid=(l+r)>>1;
      build(tree[u].lson,l,mid);
      build(tree[u].rson,mid+1,r);
}

/*int update(int i, int l, int r, int old, int val) {
      if (l == r) {
        bh++;
        tree[bh].val = val;
        return bh;
      }
      int tbh;
      int mid = (l + r) >> 1;
      if (i > mid) {
        bh++;
        tbh = bh;
        tree[bh].lson = tree[old].lson;
        tree[tbh].rson = update(i, mid + 1, r, tree[old].rson, val);
      } else {
        bh++;
        tbh = bh;
        tree[bh].rson = tree[old].rson;
        tree[tbh].lson = update(i, l, mid, tree[old].lson, val);
      }
  // printf("%d %d %d %d", i, l, r, old);
  // printf(" change->%d\n", tbh);
  // printf("lson=%d rson=%d\n", tree[tbh].lson, tree[tbh].rson);
      return tbh;
}*/
void update(int l,int r,int &x,int y,int pos,int val)
{
    if(l==r)
    {
        x=bh++;
        tree[x].val=val;
        return;
    }
    int mid=(l+r)>>1;
    if(pos>mid)
    {
        x=bh++;
        tree[x].lson=tree[y].lson;
        update(mid+1,r,tree[x].rson,tree[y].rson,pos,val);
    }else
    {
        x=bh++;
        tree[x].rson=tree[y].rson;
        update(l,mid,tree[x].lson,tree[y].lson,pos,val);
    }
}
int query(int rt, int wz, int l, int r) {
      if(l == r){
        return tree[rt].val;
      }    
      int mid = (l + r) / 2;
      if (wz <= mid) {
        return query(tree[rt].lson, wz, l, mid);
      }else{
        return query(tree[rt].rson, wz, mid + 1, r);
      }
}
int get_father(int rt,int x,int i) 
{
      int tmp=query(rt,x,1,n);
      if (tmp==0)
        return x;
      int fa=get_father(rt,tmp,i);
      update(1,n,root[i],root[i],x,fa);
      return fa;
}

int main() {
      scanf("%d%d", &n, &m);
      build(root[0],1,n);
      int lastans = 0;
      for (int i = 1; i <= m; i++) {
        scanf("%d", &cases);
        if (cases == 1) {
          scanf("%d%d", &a, &b);
          a = a ^ lastans;
          b = b ^ lastans;
          root[i] = root[i - 1];
          int fax = get_father(root[i], a, i);
          int fay = get_father(root[i], b, i);
          if (fax != fay) {
            update(1, n,root[i], root[i],fax, fay);
              }
        } else if (cases == 2) {
        scanf("%d", &a);
        a = a ^ lastans;
          root[i] = root[a];
    } else {
          scanf("%d%d", &a, &b);
          a = a ^ lastans;
          b = b ^ lastans;
          root[i] = root[i - 1];
          int fax = get_father(root[i], a, i);
          int fay = get_father(root[i], b, i);
      // printf("%d %d %d %d\n", a, fax, b, fay);
          if (fax == fay) {
            lastans = 1;
          } else {
            lastans = 0;
          }
          printf("%d\n", lastans);
    }
  }
  //system("pause");
  return 0;
}

个人觉得我的代码比hgz的精简吧

此题还能用rope瞎搞

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define maxn 200010
rope<int> *rp[maxn];
int a[maxn];
int findrep(int i,int x)
{
    if(rp[i]->at(x)==x) return x;
    int f=findrep(i,rp[i]->at(x));
    if (f==rp[i]->at(x)) return f;
    rp[i]->replace(x,f);
    return f;
}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    int x,y,lastans=0,Mode;
    for(int i=1;i<=n;i++)
    a[i]=i; 
    rp[0]=new rope<int> (a,a+n+1); 
    for(int i=1;i<=m;i++)
    {
        rp[i]=new rope<int> (*rp[i-1]);
        scanf("%d",&Mode);
        if(Mode==1)
        {
            scanf("%d %d",&x,&y);
            x^=lastans;
            y^=lastans;
            int fx=findrep(i,x),fy=findrep(i,y);
            if(fx!=fy)
            {
                rp[i]->replace(fy,fx);
            }
        }else
        if(Mode==2)
        {
            scanf("%d",&x);
            x^=lastans;
            rp[i]=rp[x];
        }else
        {
            int a,b;
            scanf("%d %d",&a,&b);
            a^=lastans,b^=lastans;
            printf("%d\n",lastans=(findrep(i,a)==findrep(i,b)));
        }
    }
    return 0;
 } 

 

posted @ 2017-09-15 22:23  dancer16  阅读(151)  评论(0编辑  收藏  举报
描述