题目
[SP2916 GSS5] Can you answer these queries V
分析
先考虑两个区间不相交的情况:只需要求 [ l 1 , r 1 ] [l_1, r_1] [l1,r1] 的前缀和最小值和 [ l 2 , r 2 ] [l_2, r_2] [l2,r2] 的前缀和最大值,相减就是答案。再考虑两个区间相交的情况,相交部分用 GSS1 解决即可,未相交部分考虑两种情况:左端点在 [ l 1 , l 2 ] [l_1, l_2] [l1,l2] 右端点在 ( l 2 , r 2 ] (l_2, r_2] (l2,r2];左端点在 [ l 1 , r 1 ] [l_1, r_1] [l1,r1] 右端点在 ( r 1 , r 2 ] (r_1, r_2] (r1,r2]。最大值支持重复计算,所以不管那么多全部取最大值即可。
代码
注意区间端点先处理一下排除不合法区间(例如 l 2 < l 1 l_2 < l_1 l2<l1)。
#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 = 10000;
#define lch (u << 1)
#define rch (u << 1 | 1)
int N, Q;
int A[MAXN + 5], S[MAXN + 5];
struct Node {
int lft, rgt, mid, tot, mx, mn;
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,
std::max(mx, other.mx), std::min(mn, other.mn)
};
}
} 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 = A[l];
T[u].mx = T[u].mn = S[l];
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 T = Read();
while (T--) {
N = Read();
for (int i = 1; i <= N; i++)
S[i] = S[i - 1] + (A[i] = Read());
Build(1, 0, N);
Q = Read();
while (Q--) {
int l1 = Read(), r1 = Read(), l2 = Read(), r2 = Read();
l2 = std::max(l2, l1), r1 = std::min(r1, r2);
if (l2 > r1)
printf("%d\n", Query(1, 0, N, l2, r2).mx - Query(1, 0, N, l1 - 1, r1 - 1).mn);
else {
int res1 = Query(1, 0, N, r1, r2).mx - Query(1, 0, N, l1 - 1, r1 - 1).mn;
int res2 = Query(1, 0, N, l2, r2).mx - Query(1, 0, N, l1 - 1, l2 - 1).mn;
int res3 = Query(1, 0, N, l2, r1).mid;
printf("%d\n", std::max(res1, std::max(res2, res3)));
}
}
}
return 0;
}