左偏树模板 指针版

一开始,我学左偏树,并不是从代码开始学,二是直接从思想开始学的。我当初只了解了一些纸上谈兵的概念,加之当时我又在研究指针,便用指针和自己的理解写了我的第一份左偏树,并把它提价交到了洛谷的[左偏树模板].(https://www.luogu.org/problemnew/show/P3377)
令我欣喜的是,他过了。虽然他的效率低,代码冗长,但作为我第一份纯靠自己写而没有参考任何代码的代码,我仍然想把他分享出来

#include<bits/stdc++.h>
#define null NULL
#define MAXN 200080
using namespace std;
struct node{
    int data,s,loc;
    node*lc;
    node*rc;
};
struct situ{
    int num;
    node*pin;
    bool exist;
}sit[MAXN];
int n,m,parent[MAXN];
inline int read(){
    register int data = 0 ;
    char ch = 0;
    while(ch<'0' || ch> '9')ch = getchar();
    while(ch <= '9' && ch >= '0'){
        data = data*10 + ch - '0';
        ch = getchar();
    }
    return data;
}
int Find (int k){
    if(k==parent[k])return k;
    parent[k]=Find(parent[k]);
    return parent[k];
}
int fi(node*&A){
    if(A==null)return -1;
    return A->s;
}
bool cmp(node*A,node*B){
    if(A->data > B->data)return 1;
    if(A->data < B->data)return 0;
    return A->loc>B->loc;
}
void fix(node *&A){
    int dis1=fi(A->lc);
    int dis2=fi(A->rc);
    if(dis1==-1&&dis2==-1){
        A->s=0;
        return;
    }
    if(dis1<dis2)swap(A->lc,A->rc);
    A->s=min(dis1,dis2)+1;
    return;
}
void unit(node*&A,node*&B)
{
    if(A->rc==null){
        A->rc=B;
        B=null;
        fix(A);
        return;
    }
    if(cmp(A->rc,B)) swap(A->rc,B);
    unit(A->rc,B);
    fix(A);
    return;
}
int main(){
    n = read();
    m = read();
    for(register int i = 1 ;i <= n; ++i) {
        sit[i].num = read() ;
        sit[i].exist = true ;
        sit[i].pin = new node ;
        sit[i].pin->data=sit[i].num;
        sit[i].pin->lc=null;
        sit[i].pin->rc=null;
        sit[i].pin->loc=i;
        sit[i].pin->s=0;
        parent[i]=i;
    }
    for(register int i = 1 ;i <= m; ++ i){
        register int a , b, c;
        a = read();
        if(a == 1){
            b=read();
            c=read();
            if(!sit[b].exist) continue;
            if(!sit[c].exist) continue;
            if(parent[b]==parent[c]) continue;
            parent[b]=Find(b);
            parent[c]=Find(c);
            if(cmp(sit[parent[c]].pin,sit[parent[b]].pin)) {
                unit(sit[parent[b]].pin,sit[parent[c]].pin);
                sit[parent[c]].pin=sit[parent[b]].pin;
                parent[parent[c]]=parent[b];
            }
            else  {
                unit(sit[parent[c]].pin,sit[parent[b]].pin);
                sit[parent[b]].pin=sit[parent[c]].pin;
                parent[parent[b]]=parent[c];
            }
        }
        else {
            b=read();
            if(!sit[b].exist){cout<<-1<<endl;continue;}
            parent[b]=Find(b);
            sit[b].pin=sit[parent[b]].pin;
            cout<<sit[b].pin->data<<endl;
            node*lp=sit[b].pin;
            sit[b].pin=lp->lc;
            node *kk=lp->rc;
            sit[lp->loc].exist=0;
            lp=null;
            delete lp;
            if(kk==null){
                sit[parent[b]].pin=sit[b].pin;
                continue;
            }
            if(cmp(sit[b].pin,kk))swap(sit[b].pin,kk);
            unit(sit[b].pin,kk);
            sit[parent[b]].pin=sit[b].pin;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值