线段树。
每个节点储存四个值,分别是:该区间内连续的最大值,从左边开始连续的最大值,从右边开始连续的最大值,整段的值。
我们知道,区间连续的最大值要么在最左边,要么在最右边,要么在中间的某一部分。
每次查询找出“完整覆盖”区间位置,从左往右暴力选择区间的起点和区间的终点。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef struct Segment{
private:
static const int MAXN = 50000 + 100;
static const ll INF = 0x3f3f3f3f3f3f3f3f;
ll perm[MAXN], seg[MAXN * 4], area, lmax[MAXN * 4], rmax[MAXN * 4], sum[MAXN * 4];
void push_up(int cur){
int u = cur << 1, v = u + 1;
seg[cur] = max(rmax[u] + lmax[v], max(seg[u], seg[v]));
lmax[cur] = max(lmax[u], sum[u] + lmax[v]);
rmax[cur] = max(rmax[v], sum[v] + rmax[u]);
sum[cur] = sum[u] + sum[v];
}
void build(int cur, int L, int R){
if(L > R) return;
if(L == R){
seg[cur] = perm[L];
lmax[cur] = perm[L];
rmax[cur] = perm[L];
sum[cur] = perm[L];
return;
}
int u = cur << 1, v = u + 1, mid = L + (R - L) / 2;
build(u, L, mid);
build(v, mid + 1, R);
push_up(cur);
}
bool Outside(int L, int R, int u, int v){
return R < u || v < L;
}
bool Inside(int L, int R, int u, int v){
return u <= L && R <= v;
}
void locate(int cur, int L, int R, int u, int v, int &k, int *A){
if(Outside(L, R, u, v)) return;
if(Inside(L, R, u, v)){
A[k++] = cur; return;
}
int mid = L + (R - L) / 2, uu = cur << 1, vv = uu + 1;
locate(uu, L, mid, u, v, k, A);
locate(vv, mid + 1, R, u, v, k, A);
}
ll query(int L, int R, int u, int v){
static int pos[MAXN];
int k = 0;
ll res = -INF;
locate(1, L, R, u, v, k, pos);
for(int i = 0; i < k; i++){
res = max(res, seg[pos[i]]);
for(int j = i + 1; j < k; j++){
ll temp = 0;
for(int t = i + 1; t < j; t++)
temp += sum[pos[t]];
temp += rmax[pos[i]] + lmax[pos[j]];
res = max(res, temp);
}
}
return res;
}
public:
void build(){
return build(1, 1, area);
}
ll query(int L, int R){
return query(1, area, L, R);
}
void read(int n){
area = n;
for(int i = 1; i <= area; i++) scanf("%lld", &perm[i]);
}
}Segment;
Segment seg;
int main(void)
{
int n;
while(~scanf("%d", &n)){
seg.read(n);
seg.build();
int k;
scanf("%d", &k);
while(k--){
int u, v;
scanf("%d%d", &u, &v);
printf("%lld\n", seg.query(u, v));
}
}
return 0;
}