BZOJ 3673: 可持久化并查集 by zky

BZOJ 3673: 可持久化并查集 by zky

标签(空格分隔): OI-BZOJ OI-可持久化数组 OI-并查集

Time Limit: 5 Sec
Memory Limit: 128 MB

Description

n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0

0<n,m<=2*10^4

Input

Output

Sample Input

5 6

1 1 2

3 1 2

2 0

3 1 2

2 1

3 1 2

Sample Output

1

0

1

Solution

可持久化数组:用可持久化线段树来储存数组的值,
对变量的查询相当于对线段树某点修改查询,实现的
时候可以在把数值存在线段树的l,r指针内,因为只有
叶节点有数值,叶节点没有孩子,利用空间。
可持久化并查集:数组可持久化
st[time]表示time时刻结束后的线段树根节点
w[0]左孩子,w[1]右孩子

听说启发式合并暴力修改啥的似乎也能过。

Code

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<bitset>
#include<vector>
using namespace std;
#define PA pair<int,int>
int read()
{
    int s=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
    return s*f;
}
//smile please
struct tree;
extern tree t[5000005];
struct tree
{
    int w[2];
}t[5000005];
int n,m,c,np,timee,la;
int st[20005];
int ask(int x,int s,int c)
{
    if(c==-1)return t[x].w[0];
    int p=(s>>c)&1;
    return ask(t[x].w[p],s-(p<<c),c-1);
}
void modif(int x,int s,int c,int num)
{
    int now=++np;
    t[now]=t[x];
    if(c==-1){t[now].w[0]=num;return;}
    int p=(s>>c)&1;
    modif(t[now].w[p],s-(p<<c),c-1,num);
    t[now].w[p]=now+1;
}
int gf(int x)
{
    int fx=ask(st[timee],x,c-1);
    if(fx==x)
       return x;
    else
      {fx=gf(fx);
       la=np+1;
       modif(st[timee],x,c-1,fx);
       st[timee]=la;
       return fx;
      }
}
int main()
{
    n=read(),m=read();
    c=ceil(log(n)/log(2));
    for(int i=1;i<=n;i++)
        la=np+1,
        modif(st[0],i,c-1,i),
        st[0]=la;
    for(timee=1;timee<=m;timee++)
       {int o=read();
        if(o==2)
           st[timee]=st[read()];
        else
           st[timee]=st[timee-1];
        if(o==1)
          {int a=read(),b=read();
           gf(a),gf(b);
           int fa=ask(st[timee],a,c-1),
               fb=ask(st[timee],b,c-1);
           if(fa!=fb)
              la=np+1,
              modif(st[timee],fa,c-1,fb),
              st[timee]=la;
          }
        if(o==3)
          {int a=read(),b=read();
           gf(a),gf(b);
           int fa=ask(st[timee],a,c-1),
               fb=ask(st[timee],b,c-1);
           printf("%d\n",fa==fb);
          }
       }
    return 0;
}

你可能感兴趣的:(BZOJ 3673: 可持久化并查集 by zky)