You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lazy Treap实现异常:懒标记失效导致子串反转功能出错

CSES「Substring Reversals」问题的Lazy Treap实现错误排查

我在解决CSES的「Substring Reversals」问题时,采用Lazy Treap实现,但懒标记机制未生效,运行结果错误。对比参考代码后未发现明显差异,我的代码如下:

#include <bits/stdc++.h>
using namespace std;
struct Node {
    int priority=rand(),sz=1;
    char value;
    bool flip=0;
    Node *l=nullptr, *r=nullptr;
    Node(char _value): value(_value){}
};
using NodePtr = Node*;
 
int get_sz(NodePtr t)
{
    return t ? t->sz : 0;
}
 
void pull_sz(NodePtr t)
{
    if(t) t->sz = get_sz(t->l) + get_sz(t->r) + 1;
}
void push_lz(NodePtr t){
    if (t && t->flip){
        t->flip = 0;
        swap(t->l,t->r);
        if (t->l) t->l->flip ^= 1;
        if (t->r) t->r->flip ^= 1;
    }
}
void split(NodePtr t, NodePtr &l, NodePtr &r, int k){
    if (!t) {
        l = r = nullptr;
        return;
    }
    int rank = get_sz(t->l) + 1;
    push_lz(t);
    if(rank <= k)
    {
        l = t;
        split(l->r, l->r, r, k-rank);
    }
    else
    {
        r = t;
        split(r->l, l, r->l, k);
    }
    pull_sz(l);
    pull_sz(r);
}
void merge(NodePtr &t, NodePtr l, NodePtr r){
    push_lz(l);
    push_lz(r);
    if(!l) t = r;
    else if(!r) t = l;
    else if (l->priority > r->priority){
        t = l;
        merge(t->r, t->r, r);
    }
    else {
        t = r;
        merge(t->l, l, t->l);
    }
    pull_sz(t);
}
 
NodePtr find_by_order(NodePtr t, int k)
{
    if(!t) return t;
    int lsz = get_sz(t->l);
    if(k == lsz)
    {
        return t;
    }
    else if(k < lsz)
    {
        return find_by_order(t->l, k);
    }
    else
    {
        return find_by_order(t->r, k-lsz-1);
    }
}
 
NodePtr build(const string& v, int lb, int rb)
{
    if(lb == rb)
    {
        return new Node(v[lb]);
    }
 
    int mb = (lb+rb)/2;
    NodePtr l = build(v, lb, mb);
    NodePtr r = build(v, mb+1, rb);
    NodePtr t;
    merge(t, l, r);
    return t;
}
 
void output(NodePtr t)
{
    if(!t) return;
    push_lz(t);
    output(t->l);
    cout << t->value;
    output(t->r);
}
 
int main(){
    int n,t;
    string s;
    cin >> n >> t;
    cin >> s;
    NodePtr tr = build(s,0,n-1);
    while (t--){
        int a,b;
        cin >> a >> b;
        a--;b--;
        NodePtr l,m,r;
        split(tr,l,m,a);
        split(m,m,r,b-a+1);
        if (m) m->flip ^= true;
        merge(tr,l,m);
        merge(tr,tr,r);
    }
    output(tr);
}

运行以下测试输入:

5 2
ABCDE
1 5
1 4

得到的错误输出为:

ABCDE

这显然不符合预期,说明懒标记未在split操作中正确传递。我的split函数与参考代码功能相似,仅索引跟踪方式不同,请问实现中存在什么问题?


更新:已找到bug——split函数中push_lz与rank计算的顺序错误,应先执行push_lz再计算rank,因为push_lz可能改变与get_sz(t->l)相关的子树结构。


内容的提问来源于stack exchange,提问作者PlainXYZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:27:12