• [BZOJ 3673&BZOJ 3674]可持久化并查集以及加强版 by zky(主席树)


    Description

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

    Solution

    用主席树维护一个可持久化的数组来进行并查集操作

    并查集按秩合并

    一开始没有路径压缩,果然被加强版卡掉了,然后改了改代码,RE了几发(于是AC率又下降了1%)

    发现数组开小了…!@#¥%…&*

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #define MAXN 200005
    using namespace std;
    int n,m,tot=0;
    int rt[MAXN],ls[MAXN*50],rs[MAXN*50],f[MAXN*50],h[MAXN*50];
    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;
    }
    void build(int &idx,int l,int r)
    {
        tot++,idx=tot;
        if(l==r){f[idx]=l,h[idx]=0;return;}
        int mid=(l+r)>>1;
        build(ls[idx],l,mid);
        build(rs[idx],mid+1,r);
    }
    int query(int idx,int l,int r,int x)
    {
        if(l==r)return idx;
        int mid=(l+r)>>1;
        if(x<=mid)return query(ls[idx],l,mid,x);
        else return query(rs[idx],mid+1,r,x);
    }
    void insert(int &idx,int last,int l,int r,int pos,int x)
    {
        tot++,idx=tot;
        ls[idx]=ls[last],rs[idx]=rs[last];
        if(l==r){f[idx]=x;h[idx]=h[last];return;}
        int mid=(l+r)>>1;
        if(pos<=mid)insert(ls[idx],ls[last],l,mid,pos,x);
        else insert(rs[idx],rs[last],mid+1,r,pos,x);
    }
    int find(int &idx,int last,int x)
    {
        int t=query(idx,1,n,x);
        if(f[t]==x)return t;
        int p=find(idx,last,f[t]);
        insert(idx,last,1,n,x,f[p]);
        return p;
    }
    int main()
    {
        n=read(),m=read();
        build(rt[0],1,n);
        int opt,a,b,k,x,y,key=0;
        for(int i=1;i<=m;i++)
        {
            opt=read();
            switch(opt)
            {
                case 1:
                    a=read(),b=read();
                    a^=key,b^=key;
                    rt[i]=rt[i-1];
                    x=find(rt[i],rt[i-1],a),y=find(rt[i],rt[i-1],b);
                    if(f[x]==f[y])continue;
                    if(h[x]==h[y])h[x]++;
                    if(h[x]<h[y])swap(x,y);
                    insert(rt[i],rt[i-1],1,n,f[y],f[x]);
                    break;
                case 2:
                    k=read();
                    k^=key;
                    rt[i]=rt[k];
                    break;
                case 3:
                    a=read(),b=read();
                    a^=key,b^=key;
                    rt[i]=rt[i-1];
                    x=find(rt[i],rt[i-1],a),y=find(rt[i],rt[i-1],b);
                    if(f[x]==f[y]){printf("1
    ");key=1;}
                    else {printf("0
    ");key=0;}
                    break;
            }
        }
        return 0;
    } 
  • 相关阅读:
    Android中Context具体解释 ---- 你所不知道的Context
    JDK6、Oracle11g、Weblogic10 For Linux64Bit安装部署说明
    matplotlib 可视化 —— 定制 matplotlib
    matplotlib 可视化 —— 移动坐标轴(中心位置)
    matplotlib 可视化 —— 移动坐标轴(中心位置)
    matplotlib 可视化 —— 定制画布风格 Customizing plots with style sheets(plt.style)
    matplotlib 可视化 —— 定制画布风格 Customizing plots with style sheets(plt.style)
    指数函数的研究
    指数函数的研究
    指数分布的研究
  • 原文地址:https://www.cnblogs.com/Zars19/p/6778602.html
Copyright © 2020-2023  润新知