mini版
题面
问题
Q1:在down函数中第二个if中一定要小于h[u],而不可以是h[x]
A:是因为在第一个if中可能会改变u的值,具体便是如下这种情况
Q2:在down函数中比较的边界必须是Size
A:因为在处理树的时候树里的元素个数是会变化的,如果非要用n来比较,那么在main函数中处理时要让n--
代码
#include<iostream>
using namespace std;
const int N = 100010;
int h[N],Size;
int m,n;
void down(int x)
{
int u = x;
//处理左子树
if(2*x<=Size && h[2*x]<h[x]) u = 2*x;
// 堆排序这里必须用U为什么?上面一步可能影响u的值
//处理右子树
if(2*x+1<=Size && h[2*x+1]<h[x]) u = 2*x+1;
if(x!=u)
{
swap(h[x],h[u]);
down(u);
}
}
int main(void)
{
cin >> n >> m;
for(int i=1;i<=n;i++) cin >> h[i];
Size = n;
for(int i= n/2;i;i--) down(i);
while(m--)
{
cout << h[1] << " ";
h[1] = h[Size--];
down(1);
}
return 0;
}
完全版
增加了几个操作如下
题面
理论推演
代码
#include<iostream>
using namespace std;
const int N = 100010;
int n,m;
int h[N],ph[N],hp[N],Size;
void heap_swap(int a,int b)
{
swap(hp[a],hp[b]);
swap(ph[hp[a]],ph[hp[b]]);
swap(h[a],h[b]);
}
void down(int x)
{
int u = x;
if(2*x <= Size && h[x] > h[2*u]) u = 2*x;
if(2*x+1 <= Size && h[u] > h[2*x+1]) u = 2*x+1;
if(u!=x)
{
heap_swap(x,u);
down(u);
}
}
void up(int x)
{
while(x/2 && h[x/2]>h[x]) heap_swap(x,x/2),x/=2;
}
int main(void)
{
int n,m=0;
cin >> n;
while(n--)
{
string s;
int x,k;
cin >> s;
if(s == "I")
{
cin >> x;
Size++;
m++;
ph[m] = Size,hp[Size] = m;
h[Size] = x;
up(Size);
}
else if(s == "PM")
{
cout << h[1] << endl;
}
else if(s == "DM")
{
heap_swap(1,Size);
Size--;
down(1);
}
else if(s == "D")
{
cin >> k;
k = ph[k];
heap_swap(k,Size);
Size--;
down(k),up(k);
}
else
{
cin >> k >> x;
k = ph[k];
h[k] = x;
down(k),up(k);
}
}
return 0;
}