社区讨论
贴一个查前驱后继的错误
P3380【模板】树套树参与者 1已保存回复 0
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @m06fjvfy
- 此快照首次捕获于
- 2024/08/23 16:08 2 年前
- 此快照最后确认于
- 2025/11/04 22:38 4 个月前
区间查前驱后继,这里写的是线段树套平衡树,但是只要外层是线段树二分,这样写就错了(其实一开始没这样写,写树状数组套线段树时想到了这个写法,但是那个东西太丑了所以改成线段树套平衡树来做错误示范)
错误写法
CPPint query_pre(int ql, int qr, int k, int p, int l = 0, int r = MAX){
if(l == r){
if(!treap::query(tr[p].rt, ql, qr)) return -INT_MAX;
return l;
}
int mid = (l + r) >> 1;
if(k <= mid + 1) return query_pre(ql, qr, k, tr[p].ls, l, mid);
if(treap::query(tr[tr[p].rs].rt, ql, qr)){
return query_pre(ql, qr, k, tr[p].rs, mid + 1, r);
}
return query_pre(ql, qr, k, tr[p].ls, l, mid);
}
int query_nxt(int ql, int qr, int k, int p, int l = 0, int r = MAX){
if(l == r){
if(!treap::query(tr[p].rt, ql, qr)) return INT_MAX;
return l;
}
int mid = (l + r) >> 1;
if(k >= mid) return query_nxt(ql, qr, k, tr[p].rs, mid + 1, r);
if(treap::query(tr[tr[p].ls].rt, ql, qr)){
return query_nxt(ql, qr, k, tr[p].ls, l, mid);
}
return query_nxt(ql, qr, k, tr[p].rs, mid + 1, r);
}
正确写法
CPPint query_pre(int ql, int qr, int k, int p, int l = 0, int r = MAX){
if(!treap::query(tr[p].rt, ql, qr)) return -INT_MAX;
if(l == r) return l;
int mid = (l + r) >> 1;
if(k <= mid + 1) return query_pre(ql, qr, k, tr[p].ls, l, mid);
int res = query_pre(ql, qr, k, tr[p].rs, mid + 1, r);
if(res == -INT_MAX) return query_pre(ql, qr, k, tr[p].ls, l, mid);
return res;
}
int query_nxt(int ql, int qr, int k, int p, int l = 0, int r = MAX){
if(!treap::query(tr[p].rt, ql, qr)) return INT_MAX;
if(l == r) return l;
int mid = (l + r) >> 1;
if(k >= mid) return query_nxt(ql, qr, k, tr[p].rs, mid + 1, r);
int res = query_nxt(ql, qr, k, tr[p].ls, l, mid);
if(res == INT_MAX) return query_nxt(ql, qr, k, tr[p].rs, mid + 1, r);
return res;
}
拿前驱举例,第一种写法是判断了“右子树与答案区间有交”后,只要右子树有值,就往右递归,但“右子树有值”不代表“右子树与答案区间的交中有值”,因此就寄了。正确写法应该是先尝试往右递归,看是否有答案,否则往左递归。
回复
共 0 条回复,欢迎继续交流。
正在加载回复...