斜堆就是每次合并必定交换左右儿子,去掉dis数组(统计高度)
来,这是洛谷p1177快速排序,可以去试试了
小根堆141ms
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
int tree[maxn],tot,n;
void Insert(int data,int pos = tot+1){
tree[++tot] = data;
while(pos!=1 && tree[pos]<tree[pos>>1])
swap(tree[pos],tree[pos>>1]),pos>>=1;
}
void del(int pos = 1){
tree[pos] = tree[tot--];
while(true){
int o = pos;
if(pos*2<=tot && tree[o]>tree[pos*2])o = pos*2;
if(pos*2+1<=tot && tree[o]>tree[pos*2+1])o = pos*2+1;
if(o == pos)break;
swap(tree[pos],tree[o]),pos = o;
}
}
int main(){
scanf("%d",&n);
for(int i=0,x;i<n;i++)scanf("%d",&x),Insert(x);
for(int i=0;i<n;i++,del())printf("%d%c",tree[1],i==n?'\n':' ');
return 0;
}
左偏树255ms
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
int tree[maxn],tot,root,n;
int l[maxn],r[maxn],dis[maxn];
int Merge(int x,int y){
if(x*y == 0)return x+y;
if(tree[x]>tree[y])swap(x,y);
r[x] = Merge(r[x],y);
if(dis[l[x]]<dis[r[x]])swap(l[x],r[x]);
dis[x] = dis[l[x]]+1;
return x;
}
int main(){
scanf("%d",&n);
for(int i=0,x;i<n;i++)scanf("%d",&x),tree[++tot] = x,root = Merge(root,tot);
for(int i=0;i<n;i++,root = Merge(l[root],r[root]))
printf("%d%c",tree[root],i==n?'\n':' ');
return 0;
}
斜堆325ms
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
int tree[maxn],tot,root,n;
int l[maxn],r[maxn];
int Merge(int x,int y){
if(x*y == 0)return x+y;
if(tree[x]>tree[y])swap(x,y);
r[x] = Merge(r[x],y);
swap(l[x],r[x]);
return x;
}
int main(){
scanf("%d",&n);
for(int i=0,x;i<n;i++)scanf("%d",&x),tree[++tot] = x,root = Merge(root,tot);
for(int i=0;i<n;i++,root = Merge(l[root],r[root]))
printf("%d%c",tree[root],i==n?'\n':' ');
return 0;
}