zoukankan      html  css  js  c++  java
  • BZOJ 3674: 可持久化并查集加强版

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

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

    分析:

    和上一题是一样的...

    一定要记得改大数据范围...

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    //by NeighThorn
    using namespace std;
    
    const int maxn=200000+5,maxm=7000000+5;
    
    int n,m,ans,tot,ls[maxm],rs[maxm],fa[maxm],siz[maxm],root[maxn];
    
    inline void build(int &x,int l,int r){
    	x=++tot;int mid=(l+r)>>1;
    	if(l==r){
    		siz[x]=1,fa[x]=l;
    		return;
    	}
    	build(ls[x],l,mid);build(rs[x],mid+1,r);
    }
    
    inline void change(int l,int r,int x,int &y,int pos,int val){
    	y=++tot;
    	if(l==r){
    		fa[y]=val,siz[y]=siz[x];
    		return;
    	}
    	int mid=(l+r)>>1;ls[y]=ls[x];rs[y]=rs[x];
    	if(pos<=mid)
    		return change(l,mid,ls[x],ls[y],pos,val);
    	else
    		return change(mid+1,r,rs[x],rs[y],pos,val); 
    }
    
    inline void add(int l,int r,int x,int pos,int val){
    	if(l==r){
    		siz[x]+=val;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(pos<=mid)
    		add(l,mid,ls[x],pos,val);
    	else
    		add(mid+1,r,rs[x],pos,val);
    }
    
    inline int query(int l,int r,int x,int pos){
    	if(l==r)
    		return x;
    	int mid=(l+r)>>1;
    	if(pos<=mid)
    		return query(l,mid,ls[x],pos);
    	else
    		return query(mid+1,r,rs[x],pos);
    }
    
    inline int find(int rt,int x){
    	int f=query(1,n,rt,x);
    	if(fa[f]==x)
    		return f;
    	return find(rt,fa[f]);
    }
    
    signed main(void){
    	scanf("%d%d",&n,&m);build(root[0],1,n);ans=0;
    	for(int i=1,opt,x,y;i<=m;i++){
    		scanf("%d",&opt);
    		if(opt==1){
    			scanf("%d%d",&x,&y);x=x^ans;y=y^ans;root[i]=root[i-1];
    			int fx=find(root[i],x),fy=find(root[i],y);
    			if(fa[fx]==fa[fy])
    				continue;
    			if(siz[fx]>siz[fy])
    				swap(fx,fy);
    			change(1,n,root[i-1],root[i],fa[fx],fa[fy]),add(1,n,root[i],fa[fy],siz[fx]);
    		}
    		else if(opt==2)
    			scanf("%d",&x),x=x^ans,root[i]=root[x];
    		else{
    			scanf("%d%d",&x,&y),root[i]=root[i-1];
    			int fx=find(root[i],x),fy=find(root[i],y);
    			if(fa[fx]==fa[fy])
    				ans=1,puts("1");
    			else
    				ans=0,puts("0");
    		}
    	}
    	return 0;
    }
    

      


    By NeighThorn

  • 相关阅读:
    设计模式-代理模式
    设计模式-桥接模式
    设计模式-组合模式
    设计模式-享元模式
    设计模式-适配器模式
    设计模式-装饰器模式
    设计模式-外观模式
    redis日志格式
    Linux下的文件切割和文件合并
    Windows server 服务器的端口突然远程连不上了,但是可以远程连接,怎么回事?
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6395117.html
Copyright © 2011-2022 走看看