zoukankan      html  css  js  c++  java
  • [模板]左偏树

    用途

    可在log复杂度合并的堆

    性质

    每个节点有一个距离,具体定义我不知道

    1.满足堆的性质

    2.左子节点距离>=右子节点

    3.节点距离=右子节点距离加1

    实现

    按照以上的性质实现merge(x,y),先选出x,y中比较大的那个(大根堆为例),再拿它的右儿子和另一个去merge,如果merge出来不符合性质2就swap一下,最后更新自己的距离

    于是也能实现pop,就是把根节点的左右孩子merge起来

    实现过程中只需要记孩子不需要记父亲,但可以仿照并查集的样子记父亲来做到给一个点查它所属的根

    例题

    luogu3377

    一开始有N个小根堆,每个堆包含且仅包含一个数。接下来需要支持两种操作:

    操作1: 1 x y 将第x个数和第y个数所在的小根堆合并(若第x或第y个数已经被删除或第x和第y个数在用一个堆内,则无视此操作)

    操作2: 2 x 输出第x个数所在的堆最小数,并将其删除(若第x个数已经被删除,则输出-1并无视删除操作)

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define CLR(a,x) memset(a,x,sizeof(a))
     4 #define MP make_pair
     5 using namespace std;
     6 typedef long long ll;
     7 const int maxn=1e5+10;
     8 
     9 inline char gc(){
    10     return getchar();
    11     static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf;
    12     return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++;
    13 }
    14 inline ll rd(){
    15     ll x=0;char c=gc();bool neg=0;
    16     while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();}
    17     while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc();
    18     return neg?(~x+1):x;
    19 }
    20 
    21 int ch[maxn][2],fa[maxn],v[maxn],dis[maxn],N,M;
    22 
    23 inline int getf(int x){
    24     while(fa[x]) x=fa[x];return x;
    25 }
    26 
    27 inline int merge(int x,int y){
    28     if(!x) return y;
    29     if(!y) return x;
    30     if(v[x]>v[y]||(v[x]==v[y]&&x>y)) swap(x,y);
    31     ch[x][1]=merge(ch[x][1],y);
    32     fa[ch[x][1]]=x;
    33     if(dis[ch[x][0]]<dis[ch[x][1]]) swap(ch[x][0],ch[x][1]);
    34     dis[x]=dis[ch[x][1]]+1;
    35     return x;
    36 }
    37 
    38 inline int pop(int x){
    39     int re=v[x];v[x]=-1;
    40     fa[merge(ch[x][0],ch[x][1])]=0;
    41     return re;
    42 }
    43 
    44 int main(){
    45     // freopen("testdata.in","r",stdin);
    46     int i,j,k;
    47     N=rd(),M=rd();
    48     for(i=1;i<=N;i++) v[i]=rd();
    49     for(i=1;i<=M;i++){
    50         int a=rd(),x=rd();
    51         if(a==1){
    52             int y=rd();
    53             if(v[x]==-1||v[y]==-1) continue;
    54             x=getf(x),y=getf(y);
    55             fa[merge(x,y)]=0;
    56         }else{
    57             if(v[x]==-1) printf("%d
    ",-1);
    58             else printf("%d
    ",pop(getf(x)));
    59         }
    60     }
    61     return 0;
    62 }
  • 相关阅读:
    js对象数组(JSON) 根据某个共同字段 分组
    一个 函数 用来转化esSearch 的range 条件
    关于 vuex 报错 Do not mutate vuex store state outside mutation handlers.
    android listview 重用view导致的选择混乱问题
    android SDK和ADT的更新
    Android中adb push和adb install的使用区别
    pycharm中添加扩展工具pylint
    su Authentication failure解决
    Putty以及adb网络调试
    有关android源码编译的几个问题
  • 原文地址:https://www.cnblogs.com/Ressed/p/10485765.html
Copyright © 2011-2022 走看看