bzoj3674: 可持久化并查集

用可持久化线段树维护可持久化并查集。

调了一下午,改为按秩合并就过了。。。

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=200100;
const int INF=1e9+10;

int n,m;
int fa[maxn];
int u,v,op;
int rk[maxn];

int bug=0;

struct SegTree
{
    int l,r;
    int ls,rs;
    int sum;
    void debug()
    {
        printf("l=%2d r=%2d ls=%2d rs=%2d sum=%2d\n",l,r,ls,rs,sum);
    }
};SegTree T[maxn*64];
int root[maxn],tot;

void push_up(int rt)
{
    T[rt].sum=T[T[rt].ls].sum+T[T[rt].rs].sum;
}

int build(int l,int r)
{
    int k=++tot;
    T[k].l=l;T[k].r=r;
    T[k].ls=-1;T[k].rs=-1;
    T[k].sum=0;
    if(l==r){
        T[k].sum=fa[l];
        return k;
    }
    int m=(l+r)>>1;
    T[k].ls=build(l,m);
    T[k].rs=build(m+1,r);
    push_up(k);
    return k;
}

int update(int rt,int p,int c)
{
    int k=++tot;
    T[k]=T[rt];
    if(T[rt].l==T[rt].r){
        T[k].sum=c;
        return k;
    }
    int m=(T[rt].l+T[rt].r)>>1;
    if(p<=m) T[k].ls=update(T[rt].ls,p,c);
    else T[k].rs=update(T[rt].rs,p,c);
    push_up(k);
    return k;
}

int query(int rt,int p)
{
    if(T[rt].l==T[rt].r) return T[rt].sum;
    int m=(T[rt].l+T[rt].r)>>1;
    if(p<=m) return query(T[rt].ls,p);
    else return query(T[rt].rs,p);
}

int find(int k,int x)
{
    int y=query(root[k],x);
    if(y==x) return x;
    else{
        int f=find(k,y);
        update(root[k],x,f);
        return f;
    }
}

int main()
{
    freopen("in.txt","r",stdin);
    while(~scanf("%d%d",&n,&m)){
        REP(i,1,n) fa[i]=i,rk[i]=1;
        root[0]=build(1,n);
        int las=0;
        REP(i,1,m){
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d",&u,&v);
                u^=las;v^=las;
                int x=find(i-1,u),y=find(i-1,v);
                if(rk[x]>rk[y]) swap(x,y);
                if(x!=y) root[i]=update(root[i-1],x,y),rk[y]+=rk[x],rk[x]=0;
                else root[i]=root[i-1];
            }
            else if(op==2){
                scanf("%d",&u);
                u^=las;
                root[i]=root[u];
            }
            else{
                scanf("%d%d",&u,&v);
                u^=las;v^=las;
                int x=find(i-1,u),y=find(i-1,v);
                if(x==y) las=1;
                else las=0;
                root[i]=root[i-1];
                printf("%d\n",las);
            }
        }
    }
    return 0;
}

时间: 2024-08-05 19:34:31

bzoj3674: 可持久化并查集的相关文章

bzoj3673可持久化并查集 by zky&amp;&amp;bzoj3674可持久化并查集加强版

bzoj3673可持久化并查集 by zky 题意: 维护可以恢复到第k次操作后的并查集. 题解: 用可持久化线段树维护并查集的fa数组和秩(在并查集里的深度),不能路径压缩所以用按秩启发式合并,可以使合并均摊复杂度为O(nlog2n).可持久化线段树实际上就是在更新节点时按主席树的插入方式新建一条路径(其实主席树就是可持久化权值线段树). 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm&g

bzoj3674 可持久化并查集加强版

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的初始值为00<n,m<=2*10^5 Samp

[BZOJ3674]可持久化并查集加强版&amp;[BZOJ3673]可持久化并查集 by zky

思路: 用主席树维护并查集森林,每次连接时新增结点. 似乎并不需要启发式合并,我随随便便写了一个就跑到了3674第一页?3673是这题的弱化版,本来写个暴力就能过,现在借用加强版的代码(去掉异或),直接吊打暴力程序. 1 #include<cstdio> 2 #include<cctype> 3 inline int getint() { 4 register char ch; 5 while(!isdigit(ch=getchar())); 6 register int x=ch

【可持久化数组】【rope】bzoj3673 bzoj3674 可持久化并查集 by zky

rope教程:http://blog.csdn.net/iamzky/article/details/38348653 Code(bzoj3673): 1 #include<cstdio> 2 #include<ext/rope> 3 using namespace std; 4 using namespace __gnu_cxx; 5 rope<int> *fa[20001]; 6 int a,b,n,m,A[20001],op; 7 int Root(int num

【BZOJ3674】可持久化并查集加强版

可持久化并查集我觉得就是可持久化数组的一种应用.可持久化数组,顾名思义,就是有历史版本的数组,那么如果我们暴力修改储存的话,修改O(n)查询O(1),空间O(n*m),这样肯定不可行,那么我们发现主席树有这样的功能,他可以快速复制,修改O(log),查询O(log),空间(m*log),是一个可行的方案.然后我们可持久化f数组维护fa,每次按照深度启发式合并,不进行路径压缩,这样能保证时间复杂度位单次O(log^2),空间复杂度为O(2*n+m*log).我不知道为什么不路径压缩,路径压缩是完全

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

http://www.lydsy.com/JudgeOnline/problem.php?id=3674 3674: 可持久化并查集加强版 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 3225  Solved: 1192[Submit][Status][Discuss] Description Description:自从zkysb出了可持久化并查集后--hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了!ndsf:暴力就可

[bzoj3673][可持久化并查集 by zky] (rope(可持久化数组)+并查集=可持久化并查集)

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 Solution 用rope实现可持久化数组,用rope的历史记录功能实现可持久化并查集,通过时间168ms

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

3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 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

BZOJ 3673: 可持久化并查集 by zky

3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 2084  Solved: 941[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