社区讨论

自己搞了个胜者树排序,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 条回复,欢迎继续交流。

正在加载回复...