题目传送门

一、手写堆的实现

#include <bits/stdc++.h>

using namespace std;
const int N = 100010;
int heap[N];
int ph[N];  //position to heap 输入序号p与堆中序号h的映射关系
int hp[N];  //heap to position 堆中序号h与输入序号p的映射关系
int sz;

//交换两个堆中的元素(a,b是指堆中序号)
void heap_swap(int a, int b) {
    swap(heap[a], heap[b]);     //交换堆中序号a与序号b的元素值
    swap(hp[a], hp[b]);         //堆中序号与输入序号的映射关系
    swap(ph[hp[a]], ph[hp[b]]); //输入序号与堆中序号的映射关系
}
void down(int u) {
    int t = u;
    if (u * 2 <= sz && heap[u * 2] < heap[t]) t = u * 2;
    if (u * 2 + 1 <= sz && heap[u * 2 + 1] < heap[t]) t = u * 2 + 1;
    if (u != t) {
        heap_swap(u, t);
        down(t);
    }
}
void up(int u) {
    while (u / 2 && heap[u] < heap[u / 2]) {
        heap_swap(u, u / 2);
        u /= 2;
    }
}
int n, m;
int main() {
    cin >> n;
    while (n--) {
        string op;
        int k, x;
        cin >> op;
        if (op == "I") {
            cin >> x;
            m++;            //输入的序号++
            sz++;           //堆内元素个数++
            ph[m] = sz;     //第m处插入的元素,它在堆中的号是sz
            hp[sz] = m;     //堆中sz号元素,它是第m个插入进来的
            heap[sz] = x;   //堆中sz号元素的值为x
            up(sz);
        }
        if (op == "PM")printf("%d\n", heap[1]);
        if (op == "DM") {
            heap_swap(1, sz); //用堆中最后一个元素替换掉1号元素
            sz--;             //删除尾部元素
            down(1);          //重排
        }
        if (op == "D") {
            cin >> k;          //第k个输入序号
            k = ph[k];         //通过ph获取到现在是堆中的堆中序号是多少
            heap_swap(k, sz);  //将第k个与最后一个交换
            sz--;              //删除尾部元素
            down(k);           //down一下,up一下
            up(k);
        }
        if (op == "C") {
            cin >> k >> x;     //第k个输入序号,修改值为x
            k = ph[k];         //根据输入序号,查找到堆中序号k
            heap[k] = x;       //将值修改为x
            down(k);           //down一下,up一下
            up(k);
        }
    }
    return 0;
}

二、STL堆的实现

#include <bits/stdc++.h>

using namespace std;
const int N = 500010;
int a[N], cnt;
multiset<int> s;
int n;
string t;
int x, k;

int main() {
    //读入优化
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> t;
        if (t == "I") {//插入一个数
            cin >> x;
            s.insert(x);
            //记录第几个是什么数
            a[++cnt] = x;
        }
        //输出当前集合中的最小值
        if (t == "PM") cout << *s.begin() << endl;
        //删除当前集合中的最小值
        //*s.begin()是堆顶值,即最小值
        if (t == "DM")
            //下面这句话的作用就是利用find找出堆顶的迭代器,然后利用s.erase进行删除
            s.erase(s.find(*s.begin()));
        //删除第k个插入的数
        if (t == "D") {
            cin >> x;
            if (s.find(a[x]) != s.end())
                s.erase(s.find(a[x]));
        }
        //修改第k个插入的数,将其变为x;
        if (t == "C") {
            cin >> k >> x;
            if (s.find(a[k]) != s.end()) s.erase(s.find(a[k]));
            a[k] = x;
            s.insert(x);
        }
    }
    return 0;
}

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-24
  • 2021-09-01
  • 2021-08-24
  • 2021-06-16
  • 2021-09-29
猜你喜欢
  • 2022-12-23
  • 2021-12-18
  • 2021-06-17
  • 2022-01-12
  • 2022-12-23
  • 2021-08-10
  • 2022-03-01
相关资源
相似解决方案