题目
[SP1043 GSS1] Can you answer these queries I
分析
线段树维护 lft, mid, rgt
分别代表选左端点的最大子段和、最大子段和、选右端点的最大子段和即可。
代码
#include <bits/stdc++.h>
int Read() {
int x = 0; bool f = false; char c = getchar();
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = x * 10 + (c ^ 48), c = getchar();
return f ? -x : x;
}
const int MAXN = 50000;
#define lch (u << 1)
#define rch (u << 1 | 1)
struct Node {
int lft, rgt, mid, tot;
Node operator + (const Node &other) const {
return {
std::max(lft, tot + other.lft),
std::max(other.rgt, other.tot + rgt),
std::max(std::max(mid, other.mid), rgt + other.lft),
tot + other.tot
};
}
} T[MAXN * 4 + 5];
void Build(const int &u, const int &l, const int &r) {
if (l == r) {
T[u].lft = T[u].rgt = T[u].mid = T[u].tot = Read();
return;
}
int mid = (l + r) >> 1;
Build(lch, l, mid);
Build(rch, mid + 1, r);
T[u] = T[lch] + T[rch];
}
Node Query(const int &u ,const int &l, const int &r, const int &lft, const int &rgt) {
if (lft <= l && r <= rgt)
return T[u];
int mid = (l + r) >> 1;
if (rgt <= mid) return Query(lch, l, mid, lft, rgt);
if (lft >= mid + 1) return Query(rch, mid + 1, r, lft, rgt);
return Query(lch, l, mid, lft, rgt) + Query(rch, mid + 1, r, lft, rgt);
}
int main() {
int N = Read();
Build(1, 1, N);
int M = Read();
while (M--) {
int lft = Read(), rgt = Read();
printf("%d\n", Query(1, 1, N, lft, rgt).mid);
}
return 0;
}