• 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集


    3673: 可持久化并查集 by zky

    Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 1878  Solved: 846
    [Submit][Status][Discuss]

    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

    HINT

    Source

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

    Time Limit: 15 Sec  Memory Limit: 256 MB
    Submit: 2367  Solved: 886
    [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

    出题人大SB++

    Solution

    先说离线的一种思路,以前yveh做Codeforces的时候告诉我一道题,与之类似,存在一个状态退回到第多少步,当时是需要线段树维护一个东西,所以可以形成一个树形结构,然后dfs并回溯离线做。

    但是这里并不能那么搞,因为并查集不支持删除所以没法回溯,所以只能考虑令并查集的 代表元素数组可持久化

    所以本质上都得用可持久化数据结构维护代表元素数组,就无所谓离线在线了。

    具体的做法就是建可持久化线段树,每次修改就在线段树上建一个新的链,叶子节点维护的是这个点的代表元素,所以方法很简单就是先初始化建出一棵新的树,然后每次新建一条链即可。

    然后这里就剩下一个问题了,就是并查集$find$,为了保证复杂度,我采用了路径压缩但这里发现路径压缩会使树上操作数增多,建很多新的节点,所以常数比较大,然后看了hxy和zyf的代码,发现她们都和hzwer写的一样,采用的按秩合并,不过常数比我还大,不过显而易见 如果不加优化一定会TLE,所以二选一即可,并无太大的差距。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define MAXN 500010 
    int N,M,last;
    namespace PrTree
    {
        int sz,lson[MAXN*20],rson[MAXN*20],root[MAXN],f[MAXN*20];
        inline void Insert(int l,int r,int &now,int fa,int pos,int val)
        {
            now=++sz;
            if (l==r) {f[now]=val; return;}
            int mid=(l+r)>>1;
            lson[now]=lson[fa],rson[now]=rson[fa];
            if (pos<=mid) Insert(l,mid,lson[now],lson[fa],pos,val);
                else Insert(mid+1,r,rson[now],rson[fa],pos,val);
        }
        inline int Query(int l,int r,int pos,int now)
        {
            if (l==r) return f[now];
            int mid=(l+r)>>1;
            if (pos<=mid) return Query(l,mid,pos,lson[now]);
                else return Query(mid+1,r,pos,rson[now]);
        }
        inline void BuildTree(int l,int r,int &now)
        {
            now=++sz;
            if (l==r) {f[now]=l; return;}
            int mid=(l+r)>>1;
            BuildTree(l,mid,lson[now]); BuildTree(mid+1,r,rson[now]);
        }
    }using namespace PrTree;
    inline int F(int x,int &rt) {int fa; if ((fa=Query(1,N,x,rt))==x) return x; else return Insert(1,N,rt,rt,x,fa=F(fa,rt)),fa;}
    inline void Merge(int x,int y,int &rt) {int fx=F(x,rt),fy=F(y,rt); if (fx!=fy) Insert(1,N,rt,rt,fx,fy);}
    int main()
    {
        N=read(),M=read();
        BuildTree(1,N,root[0]);
        for (int i=1; i<=M; i++)
            {
                root[i]=root[i-1];
                int opt=read(),x,y; 
                switch (opt)
                    {
                        case 1: x=read(),y=read(); x^=last,y^=last; Merge(x,y,root[i]); break;
                        case 2: x=read(); x^=last; root[i]=root[x]; break;
                        case 3: x=read(),y=read(); x^=last,y^=last; printf("%d
    ",last=(F(x,root[i])==F(y,root[i]))); break;
                    }
            }
        return 0;
    }

    总体来说写起来还是蛮好写的,就是自己开始手误,在可持久化线段树的时候 左右都下放的lson,然后瞪着屏幕20分钟才看出来...

  • 相关阅读:
    洛谷-P1427 小鱼的数字游戏
    洛谷-P1047 校门外的树
    洛谷-P1046 陶陶摘苹果
    洛谷-P1980 计数问题
    洛谷-P1424 小鱼的航程(改进版)
    洛谷-P1423 小玉在游泳
    洛谷-P1035 级数求和
    洛谷-P1008 三连击
    Oracle 11g r2 rac +openfiler 2.99 安装
    26 主备库并行复制策略
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/6180666.html
Copyright © 2020-2023  润新知