社区讨论
自己搞了个胜者树排序,AC了,求dalao点评
P1177【模板】排序参与者 20已保存回复 60
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 60 条
- 当前快照
- 1 份
- 快照标识符
- @mi7yldeb
- 此快照首次捕获于
- 2025/11/21 05:44 4 个月前
- 此快照最后确认于
- 2025/11/21 06:57 4 个月前
思路:将数据构造一棵胜者树,然后输出最值,将最值变成一个比胜者树里面所有值都大的值,然后重新从下到上维护这棵树,知道输出所有值为止。
CPP/*
思路:将数据构造一棵胜者树,然后输出最值,将最值变成一个比胜者树里面所有值都大的数,然后重新从下到上维护这棵树,知道输出所有值为止。
*/
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 2e5+8;
const int MAX = 0x3f3f3f3f;//定义一个比所有值大的数
int n, leaves[N], bt[N];
void build(int p) {//建树
if (bt[p*2] == -1) build(p*2);//如果这个位置并没有值,就先求出这个值
if (bt[p*2+1] == -1) build(p*2+1);//同上,这是右子节点
bt[p] = leaves[bt[p*2]] < leaves[bt[p*2+1]] ? bt[p*2] : bt[p*2+1];//通过比较求出胜者,并储存
}
void up(int p) {//由下到上调整
if (p == 1) return;
int L;
if (p % 2 == 1) L = p - 1; else L = p + 1; //求出与这个节点比较的是左兄弟节点还是右兄弟节点
bt[p/2] = leaves[bt[L]] < leaves[bt[p]] ? bt[L] : bt[p];//重新调整储存
up(p / 2);//调整父节点
}
int main() {
memset(bt, -1, sizeof(bt));
scanf("%d", &n);
for (int i=1; i<=n; i++) {
scanf("%d", &leaves[i]);//叶节点
bt[i+n-1] = i;//这里的意思是bt[1...n-1]是存放中间节点,bt[n...2*n-1]是存放一开始的节点,我认为这样更好处理
}
build(1);//从1号节点开始建树
for (int i=1; i<=n; i++) {
printf("%d ", leaves[bt[1]]);//输出1号节点,即最值
leaves[bt[1]] = MAX;
up(bt[1]+n-1);//从这一个数所在的叶节点开始调整
}
return 0;
}
评测结果:https://www.luogu.org/recordnew/show/19463853
回复
共 60 条回复,欢迎继续交流。
正在加载回复...