zoukankan      html  css  js  c++  java
  • [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;
    } 
  • 相关阅读:
    力扣算法:组合总和IV
    力扣算法:组合总和III
    逻辑回归(Logistic Regression)学习笔记
    力扣算法:组合总和II
    力扣算法:组合总和
    寒假作业(五)
    寒假作业(四)
    寒假作业(三)
    寒假作业(二)
    寒假学习(一)
  • 原文地址:https://www.cnblogs.com/Zars19/p/6778602.html
Copyright © 2011-2022 走看看