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

    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
     

    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

    正解:可持久化线段树+启发式合并。

    原来可持久化数组就是用可持久化线段树维护。。那么我们每次合并时,直接将秩小的合并到秩大的树上面,注意秩相等的时候秩要加1。询问的话就直接在线段树里找当前点的根,撤回的话直接把当前时间的根赋值成历史时间的根就行了。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define N (200010)
    15 #define il inline
    16 #define RG register
    17 #define ll long long
    18 
    19 using namespace std;
    20 
    21 int sum[80*N],dep[80*N],ls[80*N],rs[80*N],rt[N],n,m,sz,ans;
    22 
    23 il int gi(){
    24     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    25     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    26 }
    27 
    28 il void build(RG int &x,RG int l,RG int r){
    29     x=++sz; if (l==r){ sum[x]=l,dep[x]=1; return; }
    30     RG int mid=(l+r)>>1; build(ls[x],l,mid),build(rs[x],mid+1,r); return;
    31 }
    32 
    33 il void add(RG int x,RG int &y,RG int l,RG int r,RG int u){ //dep+1
    34     y=++sz; if (l==r){ sum[y]=u,dep[y]=dep[x]+1; return; }
    35     ls[y]=ls[x],rs[y]=rs[x]; RG int mid=(l+r)>>1;
    36     u<=mid ? add(ls[x],ls[y],l,mid,u) : add(rs[x],rs[y],mid+1,r,u); return;
    37 }
    38 
    39 il void merge(RG int x,RG int &y,RG int l,RG int r,RG int u,RG int fa){ //按秩合并
    40     y=++sz; if (l==r){ sum[y]=fa,dep[y]=dep[x]; return; }
    41     ls[y]=ls[x],rs[y]=rs[x]; RG int mid=(l+r)>>1;
    42     u<=mid ? merge(ls[x],ls[y],l,mid,u,fa) : merge(rs[x],rs[y],mid+1,r,u,fa); return;
    43 }
    44 
    45 il int query(RG int x,RG int l,RG int r,RG int u){ //查询当前结点的编号
    46     if (l==r) return x; RG int mid=(l+r)>>1;
    47     return u<=mid ? query(ls[x],l,mid,u) : query(rs[x],mid+1,r,u);
    48 }
    49 
    50 il int find(RG int rt,RG int u){ RG int y=query(rt,1,n,u); return sum[y]==u ? y : find(rt,sum[y]); } //找根
    51 
    52 il void work(){
    53     n=gi(),m=gi(); RG int x,y,type; build(rt[0],1,n);
    54     for (RG int i=1;i<=m;++i){
    55     type=gi(),rt[i]=rt[i-1];
    56     if (type==1){
    57         x=gi()^ans,y=gi()^ans;
    58         x=find(rt[i],x),y=find(rt[i],y);
    59         if (dep[x]>dep[y]) swap(x,y);
    60         merge(rt[i-1],rt[i],1,n,sum[x],sum[y]);
    61         if (dep[x]==dep[y]) add(rt[i],rt[i],1,n,sum[y]);
    62     } else if (type==2) x=gi()^ans,rt[i]=rt[x]; else{
    63         x=gi()^ans,y=gi()^ans;
    64         ans=sum[find(rt[i],x)]==sum[find(rt[i],y)];
    65         printf("%d
    ",ans);
    66     }
    67     }
    68     return;
    69 }
    70 
    71 int main(){
    72     work();
    73     return 0;
    74 }
  • 相关阅读:
    二人组
    对于软件工程的理解
    shell 远程链接
    shell变量
    shell教程
    正则表达式--练习
    git--版本库
    git-版本回退
    git--时光穿梭
    git安装
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6445315.html
Copyright © 2011-2022 走看看