警!示!后!人!
查看原帖
警!示!后!人!
1402161
XuHenry楼主2025/1/12 22:10

一定注意求最大子段和时合并两个区间的顺序问题!!!

struct elem {
    int max, sum, lmx, rmx;
    elem(): max(0), sum(0), lmx(0), rmx(0) {}
    elem(const int &_max, const int &_sum, const int &_lmx, const int &_rmx):
    max(_max), sum(_sum), lmx(_lmx), rmx(_rmx) {}
    // 区间修改重载运算符
    void operator=(const int &x) { max = lmx = rmx = (x > 0 ? x : 0), sum = x; }
};
// 区间合并重载运算符
elem operator+(const elem &x, const elem &y) {
    return elem(
        max({x.max, y.max, x.rmx + y.lmx}),
        x.sum + y.sum,
        max(x.sum + y.lmx, x.lmx),
        max(y.sum + x.rmx, y.rmx)
    );
}
// 以上是求最大子段和用的区间

// 注意拼接先后顺序
int query(int u, int v) {
    elem resu, resv;
    while(top[u] != top[v]) {
        if(id[u] < id[v]) swap(u, v), swap(resu, resv);
        resu = tr_query(1, id[top[u]], id[u]) + resu;
        u = f[top[u]];
    }
    // 省略后续代码~
}

以上面这段代码为例,resu 一定要放在后面合并,因为 tr_query() 查询出来的区间是倒着的。

2025/1/12 22:10
加载中...