• BZOJ3674: 可持久化并查集加强版


    题解:我们选择用一颗可持久化线段树维护来维护叶子节点的父亲 通过复杂度证明 我们可以知道按秩合并可以将查询根的时间保障在logn的范围内(因为按秩合并的实质是启发式合并 我们可以把深度作为启发量 进行合并保证合并次数只有logn次 从而查询根的复杂度只有logn) 既然和我们可以在logn的复杂度下查找到根 那我们通过可持久线段树维护以后可以在2个log的情况下查询这个点在当前版本内的集合中的根  然后我们就可以维护可持久化并查集 也能返回到其任何历史版本中

    /**************************************************************
        Problem: 3674
        User: c20161007
        Language: C++
        Result: Accepted
        Time:1124 ms
        Memory:80204 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    const int MAXN=2e5+10;
    using namespace std;
    int n,m,cnt,rt[MAXN],fa,dep,cnt1,k,a,b,op,dep1,dep2,last;
    typedef struct node{
        int l,r,f,dep;
    }node;
    node d[MAXN*25];
    int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    void built(int &x,int l,int r){
        if(!x)x=++cnt;
        if(l==r){d[x].f=l,d[x].dep=1;return ;}
        int mid=(l+r)>>1;
        built(d[x].l,l,mid);
        built(d[x].r,mid+1,r);
    }
    void update(int &x,int y,int l,int r,int t){
        x=++cnt;d[x]=d[y];
        if(l==r){d[x].f=fa;d[x].dep=dep;return ;}
        int mid=(l+r)>>1;
        if(t<=mid)update(d[x].l,d[y].l,l,mid,t);
        else update(d[x].r,d[y].r,mid+1,r,t);
    }
    int find1(int x,int l,int r,int t){
        if(l==r)return x;
        int mid=(l+r)>>1;
        if(t<=mid)return find1(d[x].l,l,mid,t);
        else return find1(d[x].r,mid+1,r,t);
    }
    int _find(int x,int num){
        while(1){
        int _t=find1(rt[num],1,n,x);
        if(d[_t].f==x)return _t;
        x=d[_t].f;
        }
    }
    int res;
    int main(){
        n=read();m=read();built(rt[0],1,n);res=0;
        for(int i=1;i<=m;i++){
        op=read();
        if(op==1){
            a=read();b=read();rt[i]=rt[i-1];
            a=a^res;b=b^res;
            a=_find(a,i);dep1=d[a].dep;
            b=_find(b,i);dep2=d[b].dep;
            if(a==b)continue;
            if(dep1>dep2)fa=d[a].f,dep=0,update(rt[i],rt[i],1,n,d[b].f);
            else if(dep1<dep2)fa=d[b].f,dep=0,update(rt[i],rt[i],1,n,d[a].f);
            else fa=d[a].f,dep=0,update(rt[i],rt[i],1,n,d[b].f),fa=d[a].f,dep=dep1+1,update(rt[i],rt[i],1,n,d[a].f);
        }
        else if(op==2)k=read(),k=res^k,rt[i]=rt[k];
        else{
            a=read();b=read();a=res^a;b=res^b;
            rt[i]=rt[i-1];
            a=_find(a,i);
            b=_find(b,i);
            if(a==b)res=1;
            else res=0;
            printf("%d
    ",res);
        }
        }
        return 0;
    }
    

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

    Time Limit: 15 Sec  Memory Limit: 256 MB
    Submit: 5025  Solved: 1887
    [Submit][Status][Discuss]

    Description

    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

    HINT

    Source

  • 相关阅读:
    HDU_1242_Rescue
    HDU_1175_连连看
    HDU_1072_Nightmare
    HDU_2544_最短路
    POJ_2195_Going Home
    POJ_3565_Ants
    KM算法(Kuhn-Munkres)
    POJ_2536_Gopher II
    ODATA 云驱动 http://www.cdata.com/cloud/
    Wijmo 5 与Breeze 的组合,及与METRONIC 的集成
  • 原文地址:https://www.cnblogs.com/wang9897/p/9426427.html
Copyright © 2020-2023  润新知