zoukankan      html  css  js  c++  java
  • BZOJ3673/3674:可持久化并查集

    Description

    n个集合 m个操作
    操作:
    1 a b 合并a,b所在集合
    2 k 回到第k次操作之后的状态(查询算作操作)
    3 a b 询问a,b是否属于同一集合,是则输出1否则输出0

    0<n,m<=2*10^4

    Input

    Output

    Sample Input

    5 6
    1 1 2
    3 1 2
    2 0
    3 1 2
    2 1
    3 1 2

    Sample Output

    1
    0
    1

    Solution

    板子题……只不过网上有很多假做法。

    具体做法就是整两个可持久化数组(不知道谁起的这么鬼畜的名字……我还是更喜欢叫他可持久化线段树)来记录并查集的$fa$数组和$dep$数组。因为路径压缩会破坏可持久化的结构,所以我们只能记录$dep$数组来按秩合并。

    网上很多只搞了一颗可持久化线段树,维护$fa$就可持久化线段树$insert$一条链,维护$dep$就修改历史版本上的点的做法是错的……已经被卡掉了QAQ

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #define N (200009)
     4 using namespace std;
     5 
     6 int n,m,lastans,opt,x,y;
     7 
     8 struct Tree
     9 {
    10     struct Sgt{int ls,rs,v;}Segt[N*20];
    11     int sgt_num,a[N],Root[N];
    12     int Build(int l,int r)
    13     {
    14         int now=++sgt_num;
    15         if (l==r) {Segt[now].v=a[l]; return now;}
    16         int mid=(l+r)>>1;
    17         Segt[now].ls=Build(l,mid);
    18         Segt[now].rs=Build(mid+1,r);
    19         return now;
    20     }
    21     int Update(int pre,int l,int r,int x,int v)
    22     {
    23         int now=++sgt_num;
    24         Segt[now].ls=Segt[pre].ls;
    25         Segt[now].rs=Segt[pre].rs;
    26         if (l==r) {Segt[now].v=v; return now;}
    27         int mid=(l+r)>>1;
    28         if (x<=mid) Segt[now].ls=Update(Segt[now].ls,l,mid,x,v);
    29         else Segt[now].rs=Update(Segt[now].rs,mid+1,r,x,v);
    30         return now;
    31     }
    32     int Query(int now,int l,int r,int x)
    33     {
    34         if (l==r) return Segt[now].v;
    35         int mid=(l+r)>>1;
    36         if (x<=mid) return Query(Segt[now].ls,l,mid,x);
    37         else return Query(Segt[now].rs,mid+1,r,x);
    38     }
    39 }CT[2];
    40 
    41 int Find(int x,int t)
    42 {
    43     int fa=CT[0].Query(CT[0].Root[t],1,n,x);
    44     return x==fa?x:Find(fa,t);
    45 }
    46 
    47 int main()
    48 {
    49     scanf("%d%d",&n,&m);
    50     for (int i=1; i<=n; ++i)
    51         CT[0].a[i]=i, CT[1].a[i]=1;
    52     CT[0].Root[0]=CT[0].Build(1,n);
    53     CT[1].Root[0]=CT[1].Build(1,n);
    54     for (int i=1; i<=m; ++i)
    55     {
    56         scanf("%d",&opt);
    57         if (opt==1)
    58         {
    59             CT[0].Root[i]=CT[0].Root[i-1];
    60             CT[1].Root[i]=CT[1].Root[i-1];
    61             scanf("%d%d",&x,&y);
    62             /*x^=lastans; y^=lastans;*/
    63             int fx=Find(x,i),fy=Find(y,i);
    64             if (fx==fy) continue;
    65             int dfx=CT[1].Query(CT[1].Root[i],1,n,fx);
    66             int dfy=CT[1].Query(CT[1].Root[i],1,n,fy);
    67             if (dfx>dfy) swap(fx,fy);
    68             CT[0].Root[i]=CT[0].Update(CT[0].Root[i],1,n,fx,fy);
    69             if (dfx!=dfy) continue;
    70             CT[1].Root[i]=CT[1].Update(CT[1].Root[i],1,n,fy,dfy+1);
    71         }
    72         if (opt==2)
    73         {
    74             scanf("%d",&x); /*x^=lastans;*/
    75             CT[0].Root[i]=CT[0].Root[x];
    76             CT[1].Root[i]=CT[1].Root[x];
    77         }
    78         if (opt==3)
    79         {
    80             CT[0].Root[i]=CT[0].Root[i-1];
    81             CT[1].Root[i]=CT[1].Root[i-1];
    82             scanf("%d%d",&x,&y);
    83             /*x^=lastans; y^=lastans;*/
    84             int fx=Find(x,i),fy=Find(y,i);
    85             if (fx==fy) puts("1")/*, lastans=1*/;
    86             else puts("0")/*, lastans=0*/;
    87         }
    88     }
    89 }
  • 相关阅读:
    docker compose 配置 redis cluster jenkins
    Spring Core
    Java Case Interview two
    pytest 生成 allure报告(含4要素的对应版本,兼容)
    python中requests库的post请求 4种类型参数
    接口测试流程
    Docker学习篇 搭建jenkins
    Pytest入门 实例
    python selenium css定位6种
    python selenium select标签的下拉框和非select标签的下拉框
  • 原文地址:https://www.cnblogs.com/refun/p/10230348.html
Copyright © 2011-2022 走看看