左偏树,就是可并堆
效率:
- | 左偏树 | 堆 |
---|---|---|
插入 | O(log n) | O(log n) |
删除 | O(log n) | O(log n) |
合并 | O(log n) | O(nlog n) |
查询 | O(1) | O(1) |
合并不是一个级别的!!!
左偏树,具有堆的性质。
且,一直往右一定比一直往左的长度短,对于每一个节点都是这样。
事实上可以直接交换左右子树,并不需要比较长度,因为这样时间慢不了多少(事实上只是一两行的区别,可是空间不知道要大多少),可是我就是要记录左右长度。
#include<bits/stdc++.h>
using namespace std;
#define fr(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
struct tree{
tree *l,*r,*f;
int v,sl,sr;
tree(){
l=r=f=NULL;
v=sl=sr=0;
}
}*root,*k,*d;
tree* merge(tree *x,tree *y){
if(x==NULL)return y;
if(y==NULL)return x;
if(x->v>y->v)
swap(x,y);
x->r=merge(x->r,y);
x->sr=x->r->sr+1;
if(x->sr>x->sl)
{
swap(x->l,x->r);
if(x->l)x->sl=s->l->sl+1;
if(s->r)x->sr=s->r->sr+1;
}
return x;
}
void insert(int x){
k=new tree;
k->v=x;
if(root==NULL)root=k;
else root=merge(root,k);
}
int top(){
if(root!=NULL)return root->v;
return -1;
}
void pop(){
if(root!=NULL)root=merge(root->l,root->r);
}
int main(){
root=NULL;
int n;
scanf("%d",&n);
fr(i,1,n){
int a;
scanf("%d",&a);
insert(a);
}
fr(i,1,n){
printf("%d ",top());
pop();
}
return 0;
}