题意:给出一个区间,m次询问,每次询问区间最大子段和。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e4 + 10;
int n, M, w, l, r;
struct node {
int sum;//[l,r]区间之和
int msum;//[l,r]内的最大子段和
int mpre;//[l,r]内的最大前缀和t
int mpost;//[l,r]内的最大后缀和
} t[N << 2];
void pushup(int rt) {
int ls = rt << 1, rs = rt << 1 | 1;
//区间之和 = 左区间之和+右区间之和
t[rt].sum = t[ls].sum + t[rs].sum;
//区间最大子段和 = max(左区间最大子段和,右区间最大子段和,左区间最大后缀和+右区间最大前缀和)
t[rt].msum = max(max(t[ls].msum, t[rs].msum), t[ls].mpost + t[rs].mpre);
//区间最大前缀和 = max(左区间最大前缀和,左区间之和+右区间最大前缀和)
t[rt].mpre = max(t[ls].mpre, t[rs].mpre + t[ls].sum);
//区间最大后缀和 = max(右区间最大后缀和,右区间之和+左区间最大后缀和)
t[rt].mpost = max(t[rs].mpost, t[ls].mpost + t[rs].sum);
}
void build(int l, int r, int rt) {
if(l == r) {
scanf("%d", &w);
t[rt].sum = t[rt].msum = t[rt].mpre = t[rt].mpost = w;
return;
}
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
pushup(rt);
}
node query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R)
return t[rt];
int m = (l + r) >> 1;
if(R <= m)
return query(L, R, l, m, rt << 1);
else if(m < L)
return query(L, R, m + 1, r, rt << 1 | 1);
else {
node ans, ls = query(L, R, l, m, rt << 1), rs = query(L, R, m + 1, r, rt << 1 | 1);
ans.sum = ls.sum + rs.sum;
ans.msum = max(max(ls.msum, rs.msum), ls.mpost + rs.mpre);
ans.mpost = max(rs.mpost, ls.mpost + rs.sum);
ans.mpre = max(ls.mpre, rs.mpre + ls.sum);
return ans;
}
}
int main() {
scanf("%d", &n);
build(1, n, 1);
scanf("%d", &M);
while(M--) {
scanf("%d%d", &l, &r);
printf("%d\n", query(l, r, 1, n, 1).msum);
}
return 0;
}