堆
堆排序
推荐:https://www.acwing.com/solution/content/120483/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int A[100100],n,m,r;
void down(int u){
int t = u;
if(2*u<=r&&A[2*u]<A[t])t=2*u;//找节点小的,交换,t是记录最小的节点
if(2*u+1<=r&&A[2*u+1]<A[t])t=2*u+1;
if(t!=u){
swap(A[t],A[u]);//交换然后递归操作
down(t);
}
}
int main()
{
cin >> n >> m;
r = n;
for (int i = 1; i <= n; i ++ ){
cin >> A[i];
}
for(int i = n/2; i >= 1; i--){
down(i);//从最后一个节点开始
}
while(m--){
cout << A[1] << " ";
swap(A[1],A[r]);
r--;//不断输出最顶上的也就是最小的
down(1);
}
return 0;
}
模拟堆
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
//每次改变后要对交换来的元素做上浮或者下沉,如果没做可能是因为本来就在其下或上
using namespace std;
vector<int> heap;
vector<int> idxtime;
vector<int> timeidx;//维护一个是次数的索引,一个是索引的次数,方便交换的时候直接查找。
int k=1;
void heap_swap(int a, int b){
swap(heap[a],heap[b]);
swap(timeidx[idxtime[a]],timeidx[idxtime[b]]);
swap(idxtime[a],idxtime[b]);
}
void down(int u){
int t=u;
if(2*u<heap.size()&&heap[2*u]<heap[t])t=2*u;
if(2*u+1<heap.size()&&heap[2*u+1]<heap[t])t=2*u+1;
if(t!=u){
heap_swap(t,u);
down(t);
}
}
void up(int u){
while(u/2>0&&heap[u]<heap[u/2]){
heap_swap(u,u/2);
u = u/2;
}
}
void ins(int a){
heap.push_back(a);
timeidx.push_back(0);
idxtime.push_back(0);
timeidx[k] = heap.size()-1;
idxtime[heap.size()-1] = k;
up(heap.size()-1);
k++;//记得递增
}
int main()
{
int n;
cin >> n;
string op;
int a,b;
heap.push_back(0);
idxtime.push_back(0);
timeidx.push_back(0);
while (n -- ){
cin >> op;
if(op=="I"){
cin >> a;
ins(a);
}
else if(op=="PM"){
cout << heap[1] << endl;
}
else if(op=="DM"){
heap_swap(1,heap.size()-1);
heap.pop_back();
idxtime.pop_back();
if(heap.size() > 1)down(1);//每次交换后要对交换来的元素做上浮或者下沉,这里不up是因为是1
}
else if(op=="D"){
cin >> a;
int x = timeidx[a];//最后是卡在这里,应该用个临时变量,不然会变
heap_swap(x,heap.size()-1);
heap.pop_back();
idxtime.pop_back();
if(heap.size() > x){down(x);up(x);}
}
else if(op=="C"){
cin >> a >> b;
heap[timeidx[a]] = b;
up(timeidx[a]);
down(timeidx[a]);
}
}
return 0;
}