首页 > 代码库 > Chapter 5. 数据结构 左偏树

Chapter 5. 数据结构 左偏树

Chapter 5. 数据结构 左偏树

Sylvia‘s I.

   代码:

//一开始有N个小根堆,每个堆包含且仅包含一个数。接下来需要支持两种操作:
//操作1: 1 x y 将第x个数和第y个数所在的小根堆合并
//(若第x或第y个数已经被删除或第x和第y个数在用一个堆内,则无视此操作)
//操作2: 2 x 输出第x个数所在的堆最小数,并将其删除
//(若第x个数已经被删除,则输出-1并无视删除操作)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define MAX 100004
#define debug(x) cerr<<#x<<‘=‘<<x<<endl

struct Tree{
    int l,r,key,dist;//l左儿子,r右儿子,key键值,dist距离 
}t[MAX];
bool del[MAX];//记录是否删除 
int father[MAX];
int n,m,x,y,temp;

int Init(int n){//并查集初始化 
    for (int i=1;i<=n;i++){
        father[i]=i;
    }
}

int Find(int x){//查找根节点 
    int k,j,r;
    r=x;
    while (r!=father[r]) r=father[r];
    k=x;
    while (k!=r){
        j=father[k];
        father[k]=r;
        k=j;
    }
    return r;
}

int merge(int k1,int k2){//合并以k1,k2为根的小根堆 
    if (k1==0||k2==0) return k1+k2;//其中一个堆为空 
    if (t[k1].key>t[k2].key) swap(k1,k2);//使k1,k2两个根中,k1的键值小 
    t[k1].r=merge(t[k1].r,k2);//递归合并 
    if (t[t[k1].r].dist>t[t[k1].l].dist)
     swap(t[k1].r,t[k1].l);//合并后右儿子的距离比左儿子大,交换 
    t[k1].dist=t[t[k1].r].dist+1;//父节点的距离=右儿子的距离+1 
    return k1;//返回根节点 
}

int main(){
    memset(del,false,sizeof(del));
    memset(t,0,sizeof(t));
    scanf("%d%d",&n,&m);
    Init(n);
    for (int i=1;i<=n;i++) scanf("%d",&t[i].key);
    while (m--){
        scanf("%d",&temp);
        if (temp==1){
            scanf("%d%d",&x,&y);
            if (del[x]||del[y]||(Find(x)==Find(y))) 
              continue;//若第x或第y个数已经被删除或第x和第y个数在同一个堆内,忽略此操作 
            int rt=merge(father[x],father[y]);//将第x个数和第y个数所在的小根堆合并
            father[father[x]]=father[father[y]]=rt;//并查集合并 
        }
        if(temp==2){
            scanf("%d",&x);
            if (del[x]) {//若第x个数已经被删除,则输出-1
                printf("-1\n");
                continue;
            }
            int k=Find(x);//查找根节点 
            del[k]=1;//记录删除 
            printf("%d\n",t[k].key);//输出最小值 
            int rt=merge(t[k].l,t[k].r);//合并左右子树 
            father[k]=father[rt]=rt;//并查集合并,
            //k作为父亲节点已经删除直接指向现在的根节点作为中转节点 
            //rt作为现在的根节点指向自己 
        }
    }
    return 0;
}

 

 

 


 

 

以倒叙的的方式还他一条生命

文刀

“躺在地上的他已无生命迹象”,

这句话,从紧急赶到的医生嘴里收了回去。

血泊中的他,逐渐有了心跳,

旁边蜂拥而至的人群散开了。

深红色的血液慢慢返回他的脑部,

血肉模糊的轮廓逐渐变得清晰,

破碎的摩托车也恢复原来的样子。

他又骑上了摩托车,

和拐弯处那辆与他相撞的卡车都开始往后退去。

一路感觉有点冷,但心底暖洋洋,

他迎风骑着摩托车,好快。

他站在阳光下,穿着洁白的短袖,

说道:儿子,我去给你买生日蛋糕,

嘴角,一撇微笑……

 


 

Sylvia

二零一七年五月二十七日

 

Chapter 5. 数据结构 左偏树