蒟蒻C++14离奇错误求调

P3391 【模板】文艺平衡树

NullNone @ 2023-07-17 18:14:11

C++14又紫又红

C++17十分正常

#include <iostream>
#include <vector>
#include <utility>
using namespace std;
struct Node{
    int prio, num, ls, rs, siz = 1;
    bool laz;
    Node(){}
    Node(int prio, int num, int ls, int rs, bool laz){
        this->prio = prio, this->num = num, this->ls = ls, this->rs = rs, this->laz = laz;
    }
    inline void print(){cerr << "Node{" << prio << ',' << num << ',' << ls << ',' << rs << ',' << laz << ',' << siz << '}' << endl;}
};
struct Treap{
    vector<Node>nodes;
    int mem = 0;
    int root = -1;
    inline int node(){
        this->nodes.push_back(Node());
        return mem++;
    }
    inline void check_laz(int cur){
        if(this->nodes[cur].laz){
            this->nodes[cur].laz = false;
            int ls = this->nodes[cur].ls, rs = this->nodes[cur].rs;
            swap(this->nodes[cur].ls, this->nodes[cur].rs);
            if(ls != -1)
                this->nodes[ls].laz ^= 1;
            if(rs != -1)
                this->nodes[rs].laz ^= 1;
        }
    }
    inline void upd_siz(int cur){
        this->nodes[cur].siz = 1;
        int ls = this->nodes[cur].ls, rs = this->nodes[cur].rs;
        if(ls != -1)
            this->nodes[cur].siz += this->nodes[ls].siz;
        if(rs != -1)
            this->nodes[cur].siz += this->nodes[rs].siz;
    }
    int build(int lt, int rt){
        if(lt == rt){
            int cur = this->node();
            this->nodes[cur] = Node(this->mem, lt, -1, -1, false);
            return cur;
        }
        int mid = (lt + rt) >> 1;
        int cur = this->node();
        this->nodes[cur] = Node(this->mem, mid, -1, -1, false);
        if(lt < mid)
            this->nodes[cur].ls = this->build(lt, mid - 1);
        this->nodes[cur].rs = this->build(mid + 1, rt);
        this->upd_siz(cur);
        return cur;
    }
    inline void build(int len){this->root = this->build(1, len);}
    pair<int, int>split(int cur, int lim){
        if(cur == -1)
            return make_pair(-1, -1);
        this->check_laz(cur);
        int lsz = 0;
        if(this->nodes[cur].ls != -1)
            lsz = this->nodes[this->nodes[cur].ls].siz;
        if(lsz < lim){
            auto rt = this->split(this->nodes[cur].rs, lim - lsz - 1);
            this->nodes[cur].rs = rt.first;
            this->upd_siz(cur);
            return make_pair(cur, rt.second);
        }else{
            auto lt = this->split(this->nodes[cur].ls, lim);
            this->nodes[cur].ls = lt.second;
            this->upd_siz(cur);
            return make_pair(lt.first, cur);
        }
    }
    int merge(int a, int b){
        if(a == -1) return b;
        if(b == -1) return a;
        this->check_laz(a);
        this->check_laz(b);
        if(this->nodes[a].prio < this->nodes[b].prio){
            this->nodes[a].rs = this->merge(this->nodes[a].rs, b);
            this->upd_siz(a);
            return a;
        }else{
            this->nodes[b].ls = this->merge(a, this->nodes[b].ls);
            this->upd_siz(b);
            return b;
        }
    }
    inline void reverse(int lt, int rt){
        auto m = this->split(this->root, rt);
        auto lm = this->split(m.first, lt - 1);
        this->nodes[lm.second].laz ^= 1;
        this->merge(this->merge(lm.first, lm.second), m.second);
    }
    void print(int cur){
        if(cur == -1)
            return;
        this->check_laz(cur);
        this->print(this->nodes[cur].ls);
        cout << this->nodes[cur].num << ' ';
        this->print(this->nodes[cur].rs);
    }
    inline void print(){this->print(this->root); cout << endl;}
}treap;
int main(int argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    int n, m, l, r;
    cin >> n >> m;
    treap.build(n);
    // treap.print();
    while(m--){
        cin >> l >> r;
        treap.reverse(l, r);
        // treap.print();
    }
    treap.print();
    return 0;
}

by CarrotMeow @ 2023-07-17 18:22:10

@NullNone 有 UB?| %%%


by Killer_joke @ 2023-07-17 18:25:12

@NullNone 盲猜是 C++17 额外规定了一些求值顺序。


by NullNone @ 2023-07-17 18:50:59

@StandardManager 请问怎么检查。用脚造小数据不会报错,大数据不好调试 | %%%


by NullNone @ 2023-07-17 18:52:13

@Killer_joke 请问代码中哪些地方容易出现求值顺序的问题


by NullNone @ 2023-07-17 18:54:17

@Killer_joke 我找不到哪里可能有问题,只知道对我来说用动态开点就容易出现离奇问题


by Killer_joke @ 2023-07-17 19:06:29

@NullNone

不建议用vector来写动态开点的数据结构。

一旦发生扩容,会导致之前保存的引用全部失效。容易引发奇怪的问题。

您可以试试在build函数里加一句

nodes.reserve(len);

by NullNone @ 2023-07-17 19:42:33

@Killer_joke 感谢巨佬 %%%


|