专栏文章
题解:P11266 【模板】完全体·堆
P11266题解参与者 2已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mir3h4ky
- 此快照首次捕获于
- 2025/12/04 15:08 3 个月前
- 此快照最后确认于
- 2025/12/04 15:08 3 个月前
由于发现没人写平衡树,于是就有了这篇题解。
核心思路
不妨用 棵平衡树 维护 个集合,使用值作为键、出现次数作为值,那么各操作分别等同于:
0 x y:如果 则删除这一项,否则将其值减一。1 x:输出 第一项的键。2 x y:枚举 的每一项 ,如果存在 则令 ,否则在 中插入这一项,然后清空 。3 x y z:相当于先执行0 x y,再将 设为 ,然后若存在 则将其值增加一,否则在 中插入 。
考虑使用
__gnu_pbds::tree 或 std::map 维护可过。参考代码
CPP#include <bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
int n, m, a[1000024];
tree<int, int> t[1000024];
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
t[i].insert({a[i], 1});
}
int tp, x, y, z;
while (m--) {
scanf("%d %d", &tp, &x);
if (tp == 0) {
scanf("%d", &y);
if (t[x][a[y]] == 1) t[x].erase(a[y]);
else t[x][a[y]]--;
}
else if (tp == 1) {
printf("%d\n", t[x].begin()->first);
}
else if (tp == 2) {
scanf("%d", &y);
for (auto&[k, v] : t[y]) {
auto it = t[x].find(k);
if (it != t[x].end()) it->second += v;
else t[x].insert({k, v});
}
t[y].clear();
}
else if (tp == 3) {
scanf("%d %d", &y, &z);
if (t[x][a[y]] == 1) t[x].erase(a[y]);
else t[x][a[y]]--;
a[y] = z;
auto it = t[x].find(z);
if (it != t[x].end()) it->second++;
else t[x].insert({z, 1});
}
}
return 0;
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...