1455: 罗马游戏 左偏树

来源:互联网 发布:淘宝牙齿矫正器的好处 编辑:程序博客网 时间:2024/06/10 01:36

学习了一下左偏树。
左偏树的性质:
1.【堆性质】:节点的关键字大等于其儿子节点的关键字
2.【左偏性质】:定义节点到最近的叶节点的距离为节点距离,任意节点的左儿子的距离大于右儿子的距离
左偏树在实现插入操作时总是从右侧插入,也就是总是让短的一侧生长,如果右侧长于左侧,那么交换左右侧,继续从右侧生长

并查集来维护QAQ

#include<bits/stdc++.h>#define N 1000005using namespace std;int n,m,f[N],l[N],r[N],d[N],v[N];bool die[N];char opt[1];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}int find(int i){    return f[i]==i?i:f[i]=find(f[i]);}int merge(int x,int y){    if (!x) return y;    if (!y) return x;    if (v[x]>v[y]) swap(x,y);    r[x]=merge(r[x],y);    if (d[l[x]]<d[r[x]]) swap(l[x],r[x]);    d[x]=d[r[x]]+1;    return x;}int main(){    n=read();    for (int i=1;i<=n;i++) v[i]=read(),f[i]=i;    m=read();    d[0]=-1;    while (m--)    {        scanf("%s",opt);        if (opt[0]=='M')        {            int x=read(),y=read();            int p=find(x),q=find(y);            if (die[x]||die[y]) continue;            if (p!=q)            {                int t=merge(p,q);                f[p]=f[q]=t;            }        }        else         {            int x=read();            if (die[x]) puts("0");            else            {                int p=find(x); die[p]=1;                printf("%d\n",v[p]);                f[p]=merge(l[p],r[p]);                f[f[p]]=f[p];            }        }    }    return 0;}
0 0