• bzoj3674 可持久化并查集


    我是萌萌的任意门

    可持久化并查集的模板题……

    做法好像很多,可以标号法,可以森林法。

    本来有O(mloglogn)的神算法(按秩合并+倍增),然而我这种鶸渣就只会写O(mlog2n)的民科算法……再加上人傻常数大如狗,速度简直虚死……

    言归正传,鉴于标号法用的不多,这里用的是森林法。又由于并查集的路径压缩只能均摊logn,如果可持久化一下就废了。所以路径压缩大可不写,正好偷偷懒。

    当然,路径压缩都省了,那按秩合并就不能不写了(要不然为啥要出加强版……)。然而我太鶸,不会写按秩合并,一向都是用按大小合并代替的……不过效果还不错,复杂度好像也是个log。

    可持久化数组好像有用vector记录修改的神写法,然而我这种鶸渣只会写可持久化线段树……本来就是nlogn了,再乘上一个logn,运行时间实在感人……

    总之,写的是可持久化线段树+按秩合并+暴力找父亲(不过貌似大家都是写的按秩合并暴力?然而明明同样O(mlog2n)的算法我就是最慢的那个……)。代码丑,不愿看……就算了……

      1 /**************************************************************
      2     Problem: 3674
      3     User: hzoier
      4     Language: C++
      5     Result: Accepted
      6     Time:1636 ms
      7     Memory:201612 kb
      8 ****************************************************************/
      9 #include<cstdio>
     10 #include<cstring>
     11 #include<algorithm>
     12 using namespace std;
     13 const int maxn=200010;
     14 int findroot(int);
     15 void mergeset(int,int);
     16 void build(int,int,int&);
     17 void modify(int,int,int&);
     18 void query(int,int,int);
     19 int copy(int);
     20 int lc[maxn<<6],rc[maxn<<6],a[maxn<<6],b[maxn<<6],root[maxn],cnt=0;
     21 int n,m,d,x,y,k,prt,size,now,ans=0;
     22 int main(){
     23     scanf("%d%d",&n,&m);
     24     build(1,n,root[0]);
     25     for(now=1;now<=m;now++){
     26         scanf("%d",&d);
     27         if(d==1){
     28             scanf("%d%d",&x,&y);
     29             x^=ans;y^=ans;
     30             root[now]=copy(root[now-1]);
     31             mergeset(x,y);
     32         }
     33         else if(d==3){
     34             scanf("%d%d",&x,&y);
     35             x^=ans;y^=ans;
     36             root[now]=copy(root[now-1]);
     37             printf("%d
    ",ans=(int)(findroot(x)==findroot(y)));
     38         }
     39         else{
     40             scanf("%d",&x);
     41             x^=ans;
     42             root[now]=copy(root[x]);
     43         }
     44     }
     45     return 0;
     46 }
     47 int findroot(int x){
     48     for(;;){
     49         k=x;
     50         query(1,n,root[now]);
     51         if(prt==x)return x;
     52         x=prt;
     53     }
     54     return x;
     55 }
     56 void mergeset(int x,int y){
     57     x=findroot(x);y=findroot(y);
     58     if(x==y)return;
     59     k=x;
     60     query(1,n,root[now]);
     61     int sx=size;
     62     k=y;
     63     query(1,n,root[now]);
     64     if(sx>size)swap(x,y);
     65     sx+=size;
     66     size=0;
     67     k=x;
     68     prt=y;
     69     modify(1,n,root[now]);
     70     k=y;
     71     size=sx;
     72     modify(1,n,root[now]);
     73 }
     74 void build(int l,int r,int &rt){
     75     rt=++cnt;
     76     if(l==r){
     77         a[rt]=l;
     78         b[rt]=1;
     79         return;
     80     }
     81     int mid=(l+r)>>1;
     82     build(l,mid,lc[rt]);
     83     build(mid+1,r,rc[rt]);
     84 }
     85 void modify(int l,int r,int &rt){
     86     rt=copy(rt);
     87     if(l==r){
     88         if(prt)a[rt]=prt;
     89         if(size)b[rt]=size;
     90         return;
     91     }
     92     int mid=(l+r)>>1;
     93     if(k<=mid)modify(l,mid,lc[rt]);
     94     else modify(mid+1,r,rc[rt]);
     95 }
     96 void query(int l,int r,int rt){
     97     if(l==r){
     98         prt=a[rt];
     99         size=b[rt];
    100         return;
    101     }
    102     int mid=(l+r)>>1;
    103     if(k<=mid)query(l,mid,lc[rt]);
    104     else query(mid+1,r,rc[rt]);
    105 }
    106 int copy(int rt){
    107     int x=++cnt;
    108     lc[x]=lc[rt];
    109     rc[x]=rc[rt];
    110     a[x]=a[rt];
    111     b[x]=b[rt];
    112     return x;
    113 }
    View Code

    尽头和开端,总有一个在等你。

  • 相关阅读:
    视觉SLAM十四讲课后习题—ch13
    视觉SLAM中涉及的各种坐标系转换总结
    《视觉SLAM十四讲》笔记(ch13)
    《视觉SLAM十四讲》笔记(ch12)
    《视觉SLAM十四讲》课后习题—ch7(更新中……)
    安装opencv_contrib(ubuntu16.0)
    《视觉SLAM十四讲》笔记(ch8)
    如何将“您没有打开此文件的权限”的文件更改为可读写的文件
    《视觉SLAM十四讲》笔记(ch7)
    ubuntu16.04下跑通LSD-SLAM的过程记录
  • 原文地址:https://www.cnblogs.com/hzoier/p/6040586.html
Copyright © 2020-2023  润新知