社区讨论
非旋Treap建树的问题
P2042[NOI2005] 维护数列参与者 5已保存回复 14
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 14 条
- 当前快照
- 1 份
- 快照标识符
- @mi86c8zu
- 此快照首次捕获于
- 2025/11/21 09:21 4 个月前
- 此快照最后确认于
- 2025/11/21 09:52 4 个月前
非旋treap笛卡尔式建树的时候我发现了一些我不能解决的问题,请大佬们帮忙看看。
CPPint Build(int c[], int num) {
static int S[kMaxn]; // 栈,维护最右链
int top = 0;
for (int i = 0, cur, last; i < num; i++) {
cur = NewNode(c[i]), last = 0; // NewNode新建一个节点,并返回定义数组下标
for (int fa; top; ) {
// rkey是随机权值,维护的是小根堆
if (T[S[top - 1]].rkey < T[cur].rkey) {
lson(cur) = rson(fa = S[top - 1]); Maintain(cur);
rson(fa) = cur; Maintain(fa);
break;
}
last = S[--top];
}
// 这里特判把栈弹空的情况
if (!top && last) {
lson(cur) = last; Maintain(cur);
}
S[top++] = cur;
}
return S[0];
}
这是我原来的代码,除了
Build函数其他函数都可以保证没有问题(暴力建树是没有WA的),Maintain函数用于维护这个节点的信息(即把儿子的信息pushup上去)。在这里建树的时候每次son的信息发生改变我就Maintain一次,但是这样只能通过第一个点,其他点全部WA。下面是AC的代码:
CPPint Build(int c[], int num) {
static int S[kMaxn];
int top = 0;
for (int i = 0, cur, last; i < num; i++) {
cur = NewNode(c[i]), last = 0;
for (int fa; top; ) {
if (T[S[top - 1]].rkey < T[cur].rkey) {
lson(cur) = rson(fa = S[top - 1]); rson(fa) = cur;
break;
}
Maintain(last = S[--top]);
}
if (!top && last) {
lson(cur) = last;
}
S[top++] = cur;
}
while (top) Maintain(S[--top]);
assert(S[0]); // 这个assert后来并没有报错
return S[0];
}
它与原来代码的唯一区别就是它是在一个点出栈的时候进行
Maintain。但是我认为这两种方法无非就是第一种进行Maintain操作次数多一些。至于为什么导致WA,我实在是看不出,请大佬们帮助我一下。感激不尽。回复
共 14 条回复,欢迎继续交流。
正在加载回复...