BZOJ 3674 可持久化并查集

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

用可持久化数组维护并查集的fa数组,

查询时间复杂度为nlognlogn,一个log是并查集的时间复杂度,采用按秩合并的操作,需要注意的是按秩合并的秩意思为当前最大结点下的树的最大深度。

另一个log是主席树查询的时间复杂度

 

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int T[maxn],tot;
struct Tree{
    int lt,rt;
    int fa,size;
}tree[maxn * 52];
int fa[maxn],Size[maxn];
void newnode(int &t){
    t = ++tot;
    tree[t].lt = tree[t].rt = tree[t].fa = 0;
}
void Build(int &t,int l,int r){
    newnode(t);
    if(l == r){
        tree[t].fa = l;
        tree[t].size = 0;
        return;
    }
    int m = l + r >> 1;
    Build(tree[t].lt,l,m); Build(tree[t].rt,m + 1,r);
}
int query(int t,int l,int r,int x){
    if(l == r){
        Size[x] = tree[t].size;
        return tree[t].fa;
    }
    int m = l + r >> 1;
    if(x <= m) return query(tree[t].lt,l,m,x);
    else return query(tree[t].rt,m + 1,r,x);
}
void update(int &t,int pre,int l,int r,int x){
    newnode(t);
    tree[t] = tree[pre];
    if(l == r){
        tree[t].fa = fa[x];
        tree[t].size = Size[x];
        return;
    }
    int m = l + r >> 1;
    if(x <= m) update(tree[t].lt,tree[pre].lt,l,m,x);
    else update(tree[t].rt,tree[pre].rt,m + 1,r,x);
}
int find(int id,int x){
    int f = query(T[id],1,N,x);
    if(f == x) return x;
    return find(id,f);
}
int main(){
    //freopen("C.in","r",stdin);
    Sca2(N,M);    
    Build(T[0],1,N);
    int ans = 0; 
    for(int i = 1; i <= M; i ++){
        int op = read();
        if(op == 1){
            int a = read() ^ ans,b = read() ^ ans;
            a = find(i - 1,a); b = find(i - 1,b);
            if(Size[a] > Size[b]) swap(a,b);
            fa[a] = b;
            update(T[i],T[i - 1],1,N,a);
            if(Size[a] == Size[b]){
                Size[b]++; fa[b] = b;
                int x;
                update(x,T[i],1,N,b);
                T[i] = x;
            } 
        }else if(op == 2){
            int k = read() ^ ans;
            T[i] = T[k];
        }else if(op == 3){
            T[i] = T[i - 1];
            int a = read() ^ ans,b = read() ^ ans;
            a = find(i,a); b = find(i,b);
            ans = (a == b);
            if(a == b) puts("1");
            else puts("0");
        }    
        
    }
    return 0;
}

 

posted @ 2019-03-25 18:53  Hugh_Locke  阅读(177)  评论(0编辑  收藏  举报