【深入浅出进阶篇】【数据结构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)。

浙公网安备 33010602011771号