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

    题目: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
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    PHP常用代码大全(新手入门必备)
    一代大商孟洛川的经商之道
    Photoshop调出田园照片唯美手绘油画效果
    Photoshop调出外景婚片蓝色小清新艺术效果
    photoshop快速把新照片制作成老照片教学
    Photoshop调出清晰的阴雨天气山水风景照
    PS调出清新风格社区街拍照片
    PS调出韩式米黄色室内婚纱照片
    PS调出唯美紫蓝色天空背景女生照片
    PS快速调出天蓝色清新外景
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5069896.html
Copyright © 2011-2022 走看看