zoukankan      html  css  js  c++  java
  • bzoj 3673: 可持久化并查集 by zky

    Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 1229  Solved: 561
    [Submit][Status][Discuss]

    Description

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

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

    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
     
    题解:
      用可持久化线段树维护并查集的信息,每棵线段树的叶子节点的fa值就是在当前线段树的时间下这个叶子节点表示的集合所在的根集合。查找操作就是不断地找叶子节点,如果这个叶子节点维护的fa值不是自己,就回到根节点找他fa的fa。
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<vector>
     8 #include<queue>
     9 using namespace std;
    10 const int maxn=3*1e4;
    11 int N,M;
    12 struct Tree{
    13     int lc,rc,fa;
    14 }tr[40*maxn];
    15 int root[maxn],siz;
    16 inline void build(int &i,int l,int r){
    17     i=++siz;
    18     if(l==r){
    19         tr[i].fa=l; return ;
    20     }
    21     int mid=(l+r)>>1;
    22     if(l<=mid) build(tr[i].lc,l,mid);
    23     if(mid+1<=r) build(tr[i].rc,mid+1,r);
    24 }
    25 inline void change(int last,int &i,int l,int r,int pos,int now){
    26     i=++siz;
    27     tr[i].lc=tr[last].lc; tr[i].rc=tr[last].rc;
    28     if(l==r){
    29         tr[i].fa=now; return ;
    30     }
    31     int mid=(l+r)>>1;
    32     if(pos<=mid) change(tr[last].lc,tr[i].lc,l,mid,pos,now);
    33     else change(tr[last].rc,tr[i].rc,mid+1,r,pos,now);
    34 }
    35 inline int query(int i,int l,int r,int pos){//返回叶节点为 pos的节点编号 
    36     if(l==r) return i;
    37     int mid=(l+r)>>1;
    38     if(pos<=mid) query(tr[i].lc,l,mid,pos);
    39     else query(tr[i].rc,mid+1,r,pos);
    40 }
    41 inline int find(int i,int pos){//找到pos所在集合的根节点 
    42     int x=query(i,1,N,pos);
    43     if(tr[x].fa==pos) return x;
    44     return find(i,tr[x].fa); 
    45 }
    46 int main(){
    47     scanf("%d%d",&N,&M);
    48     build(root[0],1,N);//初始化 
    49     for(int i=1,kin,a,b;i<=M;i++){
    50         scanf("%d",&kin);
    51         if(kin==1){//合并 a b
    52             root[i]=root[i-1];
    53             scanf("%d%d",&a,&b);
    54             int p=find(root[i],a),q=find(root[i],b);
    55             if(tr[p].fa!=tr[q].fa){
    56                 change(root[i-1],root[i],1,N,tr[p].fa,tr[q].fa);
    57             }
    58         }
    59         else if(kin==2){//回到第a次操作前 
    60             scanf("%d",&a);
    61             root[i]=root[a];
    62         }
    63         else if(kin==3){//判断是否在同一集合 
    64             root[i]=root[i-1];
    65             scanf("%d%d",&a,&b);
    66             int p=find(root[i],a),q=find(root[i],b);
    67             if(tr[p].fa==tr[q].fa) puts("1");
    68             else puts("0");
    69         }
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    hdu 3342 Legal or Not 拓排序
    hdu 1596 find the safest road Dijkstra
    hdu 1874 畅通工程续 Dijkstra
    poj 2676 sudoku dfs
    poj 2251 BFS
    poj Prime Path BFS
    poj 3278 BFS
    poj 2387 Dijkstra 模板
    poj 3083 DFS 和BFS
    poj 1062 昂贵的聘礼 dijkstra
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5239368.html
Copyright © 2011-2022 走看看