bzoj 3673&&3674 可持久化并查集 可持久化线段树

来源:互联网 发布:java获取文件绝对路径 编辑:程序博客网 时间:2024/04/27 16:53

用可持久化线段树维护可持久化数组。
按秩合并和按size合并都是把小的合到大的上。
贴一个路径压缩+按秩合并的吧(跑得最慢)

#include <bits/stdc++.h>using namespace std;#define N 210000#define M 10000000#define ls l,mid,ch[now][0]#define rs mid+1,r,ch[now][1]int n,m,now;struct array{    int root[N],ch[M][2],val[M],cnt;    void build(int l,int r,int &now,int tp)    {        now=++cnt;        if(l==r){val[now]=tp ? 0:l;return;}        int mid=(l+r)>>1;        build(ls,tp);build(rs,tp);    }    void insert(int l,int r,int &now,int pos,int v)    {        int t=now;now=++cnt;        if(l==r){val[now]=v;return;}        int mid=(l+r)>>1;        ch[now][0]=ch[t][0];        ch[now][1]=ch[t][1];        if(mid>=pos)insert(ls,pos,v);        else insert(rs,pos,v);    }    void mdf(int x,int y)    {insert(1,n,root[now],x,y);}    int query(int l,int r,int now,int pos)    {        if(l==r)return val[now];        int mid=(l+r)>>1;        if(mid>=pos)return query(ls,pos);        else return query(rs,pos);    }    int g(int x){return query(1,n,root[now],x);}}size,fa;int find(int x){    int t=fa.g(x);    if(t==x)return x;    t=find(t);fa.mdf(x,t);    return t;}int main(){    //freopen("tt.in","r",stdin);    scanf("%d%d",&n,&m);    fa.build(1,n,fa.root[0],0);    size.build(1,n,size.root[0],1);    for(int i=1,tp,a,b;i<=m;i++)    {        scanf("%d",&tp);        now=i;        size.root[i]=size.root[i-1];        fa.root[i]=fa.root[i-1];        if(tp==1)        {            scanf("%d%d",&a,&b);            int x=find(a),y=find(b);            int sx=size.g(x),sy=size.g(y);            if(x==y)continue;            if(sx>sy)swap(x,y),swap(sx,sy);            if(sx==sy)size.mdf(y,sy+1);            fa.mdf(x,y);        }        if(tp==2)        {            scanf("%d",&a);            size.root[i]=size.root[a];            fa.root[i]=fa.root[a];        }        if(tp==3)        {            scanf("%d%d",&a,&b);            printf("%d\n",find(a)==find(b));        }    }    return 0;}
0 0
原创粉丝点击