## [$GSS1$ - $Can$ $you$ $answer$ $these$ $queries$ $I$](https://www.luogu.com.cn/problem/SP1043) [SPOJ](https://www.spoj.com/problems/GSS1/en/) 看题意看洛谷,有中文题意解析。 提交代码用$SPOJ$,洛谷提交代码经常超时,$SPOJ$也挺慢,但能用。 ### 一、大致题意 $q$ 个询问,求 $[x,y]$ 的最大子段和。 线段树,维护 $[x,y]$ 的 $(lmax,rmax,sum,tmax)$ ,向上合并即可。 但是注意询问过程中也需要维护这些信息。 ### 二、实现代码 ```cpp {.line-numbers} #include #include #include #include using namespace std; const int N = 1e6 + 10; typedef long long LL; int n, m, a[N]; struct Node { int l, r; int lmax; int rmax; int tmax; int sum; } tr[N << 2]; void calc(Node &u, Node &l, Node &r) { u.sum = l.sum + r.sum; u.lmax = max(l.lmax, l.sum + r.lmax); u.rmax = max(r.rmax, r.sum + l.rmax); u.tmax = max({l.tmax, r.tmax, l.rmax + r.lmax}); } void pushup(int u) { calc(tr[u], tr[u << 1], tr[u << 1 | 1]); } void build(int u, int l, int r) { tr[u] = {l, r, 0, 0, 0, 0}; if (l == r) { tr[u].sum = tr[u].lmax = tr[u].rmax = tr[u].tmax = a[l]; return; } int mid = (l + r) >> 1; build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r); pushup(u); } Node query(int u, int l, int r) { if (l <= tr[u].l && r >= tr[u].r) return tr[u]; int mid = tr[u].l + tr[u].r >> 1; if (l > mid) return query(u << 1 | 1, l, r); if (r <= mid) return query(u << 1, l, r); Node a = query(u << 1, l, r), b = query(u << 1 | 1, l, r), res; calc(res, a, b); return res; } int main() { ios::sync_with_stdio(false), cin.tie(0); cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; build(1, 1, n); cin >> m; int x, y; while (m--) { cin >> x >> y; printf("%d\n", query(1, x, y).tmax); } return 0; } ```