bzoj3673可持久化并查集

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

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

可持久化并查集是用可持久化线段树维护的,唯一的区别就在于多了一个find操作,可持久化线段树实际上只维护了一个可持久化数组,只需要维护最下面的一层即可

/**************************************************************
    Problem: 3673
    User: walfy
    Language: C++
    Result: Accepted
    Time:120 ms
    Memory:13096 kb
****************************************************************/
 
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
//#define ls l,m,rt<<1
//#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)
 
using namespace std;
 
const double g=10.0,eps=1e-12;
const int N=20000+10,maxn=1200000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
 
int ls[N*50],rs[N*50],rt[N],tot,val[N*50];
int n,m;
void build(int &o,int l,int r)
{
    o=++tot;
    if(l==r)
    {
        val[o]=l;
        return ;
    }
    int m=(l+r)>>1;
    build(ls[o],l,m);build(rs[o],m+1,r);
}
void update(int &o,int l,int r,int last,int pos,int x)
{
    o=++tot;
    ls[o]=ls[last];rs[o]=rs[last];
    if(l==r)
    {
        val[o]=x;
        return ;
    }
    int m=(l+r)>>1;
    if(pos<=m)update(ls[o],l,m,ls[last],pos,x);
    else update(rs[o],m+1,r,rs[last],pos,x);
}
int query(int o,int l,int r,int pos)
{
    if(l==r)return val[o];
    int m=(l+r)>>1;
    if(pos<=m)return query(ls[o],l,m,pos);
    else return query(rs[o],m+1,r,pos);
}
int Find(int &o,int x)
{
    int te=query(o,1,n,x);
    if(te==x)return x;
    else
    {
        int pp=Find(o,te);
        update(o,1,n,o,te,pp);
        return pp;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    build(rt[0],1,n);
    for(int i=1;i<=m;i++)
    {
        int op;
        scanf("%d",&op);
        if(op==1)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            int fx=Find(rt[i-1],x),fy=Find(rt[i-1],y);
            if(fx==fy)rt[i]=rt[i-1];
            else update(rt[i],1,n,rt[i-1],fx,fy);
        }
        else if(op==2)
        {
            int x;scanf("%d",&x);
            rt[i]=rt[x];
        }
        else
        {
            int x,y;scanf("%d%d",&x,&y);
            int fx=Find(rt[i-1],x),fy=Find(rt[i-1],y);
            if(fx==fy)puts("1");
            else puts("0");
            rt[i]=rt[i-1];
        }
    }
    return 0;
}
/********************
 
********************/
View Code

 

posted @ 2018-04-12 11:27  walfy  阅读(220)  评论(0编辑  收藏  举报