【深入浅出进阶篇】【数据结构2-1 二叉堆与树状数组】 题解

P3378【模板】堆

非常简单的一道模板题,解决也很简单 STL万岁

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int tt; cin >> tt;
    priority_queue<int, vector<int>, greater<int>> pq;
    while(tt --)
    {
        int op; cin >> op;
        if(op == 1){ int x; cin >> x, pq.push(x); }
        if(op == 2) cout << pq.top() << "\n";
        if(op == 3) pq.pop();
    }
    return 0;
}

想看二叉堆的,看这里其实是主播找不到C++的了

P1801 黑匣子

抱歉,主播未完成

P1090 [NOIP 2004 提高组] 合并果子

有一点点数学,我们可以知道,我们应该要从小到大合并即可。为什么呢?好问题,我也不知道 看这里

于是,我们可以知道答案:

#include<bits/stdc++.h>
using namespace std;
priority_queue<int, vector<int>, greater<int>> pq;
int main()
{
    cin.tie(0)->ios::sync_with_stdio(0);
    int n, ans = 0; cin >> n;
    while(n --)
    {
        int x; cin >> x, pq.push(x);
    }
    while(pq.size() > 1)
    {
        int a = pq.top(); pq.pop();
        int b = pq.top(); pq.pop();
        pq.push(a + b), ans += a + b;
    }
    cout << ans << endl;
    return 0;
}

P2168 [NOI2015] 荷马史诗

本题其实就是模板题。是k叉Huffman树的模板题。

看这里:这里这里,讲的相当可以

码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
struct HomericEpics
{
    int w, h;
    HomericEpics(int w, int h) : w(w), h(h) {}
    bool operator < (const HomericEpics & a) const
    {
        return a.w == w ? a.h < h :a.w < w;
    }
};
priority_queue<HomericEpics> pq;
signed main()
{
    cin.tie(0)->ios::sync_with_stdio(0);
    int n, k, ans = 0; cin >> n >> k;
    for(int i = 1;i <= n;i ++)
    {
        int w; cin >> w;
        pq.push(HomericEpics(w, 1));
    }
    while((pq.size() - 1) % (k - 1) != 0)
    {
        pq.push(HomericEpics(0, 1));
    }
    while((int)(pq.size()) >= k)
    {
        int h = -1, w = 0;
        for(int i = 1;i <= k;i ++)
        {
            HomericEpics t = pq.top(); pq.pop();
            h = max(h, t.h), w += t.w;
        }
        ans += w, pq.push(HomericEpics(w, h + 1));
    }
    cout << ans << "\n" << pq.top().h - 1 << "\n";
    return 0;
}

P1168 中位数

解决方法:使用对顶堆,左边的堆保存中位数以及中位数之前的内容,堆顶就是中位数,右边的堆保存中位数右边的内容。

始终保持左边的堆大小比右边的大1,就需要平衡操作。

代码:

#include<bits/stdc++.h>
using namespace std;
namespace mid
{
    inline int read()
    {
        int a = 0, b = 1, c = getchar();
        while(!isdigit(c))
        {
            if(c == '-') b = -1;
            c = getchar();
        }
        while(isdigit(c))
        {
            a = (a << 1) + (a << 3) + (c ^ 48);
            c = getchar();
        }
        return a * b;
    }
    inline void put(int x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x > 9) put(x / 10);
        putchar(x % 10 + '0');
    }
    inline void print(int x)
    {
        put(x), putchar('\n');
    }
    #define vi 
    #define gi 
    priority_queue<int> left;
    priority_queue<int, vector<int>, greater<int>> right;
    int main()
    {
        int n = read();
        for(int i = 1;i <= n;i ++)
        {
            int x = read();
            if(left.empty() || x <= left.top())
                left.push(x);
            else right.push(x);
            while(left.size() > right.size() + 1)
            {
                right.push(left.top()), left.pop();
            }
            while(right.size() > left.size())
            {
                left.push(right.top()), right.pop();
            }
            if(i % 2 == 1) print(left.top());
        }
        return 0;
    }
};
int main(){ return mid::main(); }

一定要用namespace包着,因为left和right和std里面的std::left和std::right重复!
解决办法:1.用namespace包着(看“命名冲突”部分)
2.不写using namespace std;,对每一个std成员函数都在前面加std::(如std::cout)
3.更换变量名(如将left改成pq1,right改成pq2)。

posted @ 2026-06-12 19:11  熊晨曦  阅读(1)  评论(0)    收藏  举报