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

主席树。

我分不清主席树和可持久化线段树。。

用主席树记录历史版本。

然后每个节点保存一个深度,代表以自己为根的树的深度。

合并时将深度小的树合进深度大的树。

3673也是一样的,不过那道题不强制在线。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 200000 + 10;
const int maxm = 5000000 + 10;

int n,m,vid;
int root[maxn],lc[maxm],rc[maxm],v[maxm],dep[maxm]; 

void build(int &x,int l,int r) {
    if(!x) x=++vid;
    if(l==r) {v[x]=l;return;}
    int mid=(l+r)>>1;
    build(lc[x],l,mid);
    build(rc[x],mid+1,r);
}

void modify(int &x,int y,int l,int r,int pos,int val) {
    x=++vid;
    if(l==r) {v[x]=val; dep[x]=dep[y]; return;}
    lc[x]=lc[y]; rc[x]=rc[y];
    int mid=(l+r)>>1;
    if(pos<=mid) modify(lc[x],lc[y],l,mid,pos,val);
    else modify(rc[x],rc[y],mid+1,r,pos,val);
}

int query(int x,int l,int r,int pos) {
    if(l==r) return x;
    int mid=(l+r)>>1;
    if(pos<=mid) return query(lc[x],l,mid,pos);
    else return query(rc[x],mid+1,r,pos);    
}

void add(int x,int l,int r,int pos) {
    if(l==r) {dep[x]++; return;}
    int mid=(l+r)>>1;
    if(pos<=mid) add(lc[x],l,mid,pos);
    else return add(rc[x],mid+1,r,pos);    
}

int find(int x,int k) {
    int p=query(x,1,n,k);
    if(v[p]==k) return p;
    else return find(x,v[p]);
}

int op,a,b;

int main() {
    scanf("%d%d",&n,&m);
    build(root[0],1,n);    
    for(int i=1;i<=m;i++) {
        scanf("%d",&op);
        if(op==1) {
            root[i]=root[i-1];
            scanf("%d%d",&a,&b);
            int p=find(root[i],a),q=find(root[i],b);
            if(v[p]==v[q]) continue;
            if(dep[p]>dep[q]) swap(p,q);
            modify(root[i],root[i-1],1,n,v[p],v[q]);
            if(dep[p]==dep[q]) add(root[i],1,n,v[q]);
        }
        else if(op==2) {
            scanf("%d",&a);
            root[i]=root[a];
        }
        else {
            root[i]=root[i-1];
            scanf("%d%d",&a,&b);
            int p=find(root[i],a),q=find(root[i],b);
            printf("%d\n",v[p]==v[q]?1:0);
        }
    }
    return 0;
}
posted @ 2016-07-12 16:10  invoid  阅读(230)  评论(0编辑  收藏  举报