一定注意求最大子段和时合并两个区间的顺序问题!!!
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() 查询出来的区间是倒着的。