码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-12-23 15:48:11      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3674

用可持久化线段树维护可持久化数组,加上启发式合并,就成了可持久化并查集。。

用root数组来记录当前是第x次操作之后的情景,这样我们就可以返回某次操作之后了。

注意一直都是维护点的pos,画个图出来应该就比较清楚吧TAT

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r; i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 200500
using namespace std;
int root[maxn],dep[maxn*21],fa[maxn*21],ls[maxn*21],rs[maxn*21];
int a,b,x,y,n,m,cnt,ans;
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch==-) f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-0; ch=getchar();}
    return x*f;
}
void build(int &i,int l,int r){
    if (!i) i=++cnt;
    if (l==r){
        fa[i]=l; return;
    }
    int mid=(l+r)/2;
    build(ls[i],l,mid); build(rs[i],mid+1,r);
}
int ask(int i,int l,int r,int val){
    if (l==r) return i;
    int mid=(l+r)/2;
    if (val<=mid) return ask(ls[i],l,mid,val);
    else return ask(rs[i],mid+1,r,val);
}
int find(int i,int x){
    int tmp=ask(i,1,n,x);
    if (fa[tmp]==x) return tmp;
    else return find(i,fa[tmp]);
}
void un(int l,int r,int x,int &y,int pos,int val){
    y=++cnt;
    if (l==r) {fa[y]=val; dep[y]=dep[x];return;}
    int mid=(l+r)/2;
    ls[y]=ls[x],rs[y]=rs[x];
    if (pos<=mid) un(l,mid,ls[x],ls[y],pos,val);
    else un(mid+1,r,rs[x],rs[y],pos,val);
}
void add(int i,int l,int r,int pos){
    if (l==r) {dep[i]++; return;}
    int mid=(l+r)/2;
    if (pos<=mid) add(ls[i],l,mid,pos);
    else add(rs[i],mid+1,r,pos); 
}
int main(){
    n=read(); m=read();
    build(root[0],1,n);
    rep(i,1,m){
        int op=read();
        if (op==1){
            root[i]=root[i-1];
            a=read()^ans; b=read()^ans;
            x=find(root[i],a); y=find(root[i],b);    
            if (fa[x]==fa[y]) continue;
            if (dep[x]>dep[y]) swap(x,y);
            un(1,n,root[i-1],root[i],fa[x],fa[y]);
            if (dep[x]==dep[y]) add(root[i],1,n,fa[y]);
        }
        else if (op==2) {
            x=read()^ans; root[i]=root[x];
        }
        else {
            root[i]=root[i-1];
            a=read()^ans; b=read()^ans;
            x=find(root[i],a); y=find(root[i],b);
            if (fa[x]!=fa[y]) ans=0;
            else ans=1;
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

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

标签:

原文地址:http://www.cnblogs.com/ctlchild/p/5069896.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!