左偏树模板

题目

测试题目传送门

Code

//By zuiyumeng
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Re register
#define Ms(a,b) memset((a),(b),sizeof(a))
#define Fo(i,a,b) for(Re int i=(a),_=(b);i<=_;i++)
#define Ro(i,a,b) for(Re int i=(b),_=(a);i>=_;i--)
using namespace std;

inline int read() { 
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x*f;
}

const int N=1e5+10;
int n,m;
int fa[N],nd[N][2],dis[N],val[N]; // 
bool deld[N]; //是否删除过 1表示已删除

int getro(int x) {return fa[x]=fa[x]==x?x:getro(fa[x]);} 

#define ls nd[x][0]
#define rs nd[x][1]
int merge(int x,int y) {
    if(!x||!y) return x+y;
    if(val[x]>val[y]) swap(x,y);
    if(val[x]==val[y]&&x>y) swap(x,y);//题目要求:最小值相同时优先删除编号最小的
    fa[rs=merge(rs,y)]=x;
    if(dis[ls]<dis[rs]) swap(ls,rs);
    dis[x]=dis[rs]+1;
    return x;
}

int main() {
    n=read(); m=read();
    dis[0]=-1; //代表所有空点的dis值为-1,因为nd[]初始全为0
    Fo(i,1,n) val[i]=read(),fa[i]=i;
    Fo(i,1,m) {
        int opt=read();
        if(opt==1) {
            int x=read(),y=read();
            if(deld[x]||deld[y]) continue;
            int rx=getro(x),ry=getro(y);
            if(rx==ry) continue;
            fa[rx]=fa[ry]=merge(rx,ry);
        } else {
            int x=read(); 
            if(deld[x]) {cout<<"-1"<<endl;continue;}
            x=getro(x);
            cout<<val[x]<<endl;
            deld[x]=1; //简单的删除操作
            fa[x]=fa[ls]=fa[rs]=merge(ls,rs);//由于使用了路径压缩,有很多点fa[]值为x,所以不如直接fa[x]=新根
        }
    }
    return 0;
}
本文版权归作者所有,未经允许不得转载。
原文地址:https://www.cnblogs.com/zuiyumeng/p/13545936.html