题目连接:https://www.spoj.com/problems/GSS1/en/
题意:给你n个数,有q个询问,l,r,求区间内最大连续字段和
线段树维护区间的最大字段和maxx,最大左字段和maxl,最大又字段和maxr,区间和sum,即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 5e4 + 10;
int n, q, a[maxn];
struct Tree {
int l, r;
ll sum, maxl, maxr, maxx;
}e[maxn << 2];
inline void pushup(int cur) {
e[cur].maxx = max(e[cur << 1].maxx, max(e[cur << 1 | 1].maxx, e[cur << 1].maxr + e[cur << 1 | 1].maxl));
e[cur].maxl = max(e[cur << 1].maxl, e[cur << 1].sum + e[cur << 1 | 1].maxl);
e[cur].maxr = max(e[cur << 1 | 1].maxr, e[cur << 1 | 1].sum + e[cur << 1].maxr);
e[cur].sum = e[cur << 1].sum + e[cur << 1 | 1].sum;
}
inline void build (int l, int r, int cur) {
e[cur].l = l;
e[cur].r = r;
e[cur].maxl = e[cur].maxr = e[cur].maxx = e[cur].sum = 0;
if(l == r) {
e[cur].maxl = e[cur].maxr = e[cur].maxx = e[cur].sum = a[l];
return ;
}
int mid = l + r >> 1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
pushup(cur);
}
inline Tree query(int cur, int l, int r) {
if(l <= e[cur].l && e[cur].r <= r){
return e[cur];
}
int mid = e[cur].l + e[cur].r >> 1;
if(r <= mid) return query(cur << 1, l, r);
else if(l > mid) return query(cur << 1 | 1, l, r);
else {
Tree l1 = query(cur << 1, l, r);
Tree l2 = query(cur << 1 | 1, l, r);
Tree ans;
ans.maxx = max(l1.maxx, max(l2.maxx, l1.maxr + l2.maxl));
ans.maxl = max(l1.maxl, l1.sum + l2.maxl);
ans.maxr = max(l2.maxr, l2.sum + l1.maxr);
ans.sum = l1.sum + l2.sum;
return ans;
}
}
int main()
{
while(~scanf("%d", &n)) {
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
build(1, n, 1);
scanf("%d", &q);
while(q--) {
int l, r;
scanf("%d %d", &l, &r);
printf("%lld\n", query(1, l, r).maxx);
}
}
return 0;
}