SPOJ GSS系列题
You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). A query is defined as follows:
Query(x,y) = Max { a[i]+a[i+1]+...+a[j] ; x ≤ i ≤ j ≤ y }.
Given M queries, your program must output the results of these queries.
Input
- The first line of the input file contains the integer N.
- In the second line, N numbers follow.
- The third line contains the integer M.
- M lines follow, where line i contains 2 numbers xi and yi.
Output
- Your program should output the results of the M queries, one query per line.
Example
Input: 3 -1 2 3 1 1 2 Output: 2
GSS1
题意
维护一个数列a[1], a[2], ..., a[N] . (|a[i]| ≤ 15007, 1 ≤ N ≤ 50000)。
有一种共M个操作:Query(x, y) = max{a[i] + a[i + 1] + ... + a[j]; x ≤ i ≤ j ≤ y}。
题解
用线段树维护四个值:maxs,maxl,maxr,alls,分别表示一个区间的最大和、左起最大和、右起最大和与整段和。连续数的最大和有三种情况:都在左半边,都在右半边,横跨左右两边。
代码
#include <algorithm>
#include <cstdio>
using namespace std;
#define lc cur << 1
#define rc (cur << 1) + 1
const int MAXN = 50000, INF = 1000000000;
struct interval_tree
{
struct data
{
int alls, maxs, maxl, maxr;
inline data(int x = 0)
{
alls = maxs = maxl = maxr = x;
}
} d[MAXN << 2];
inline data update(data x, data y)
{
data ret;
ret.alls = x.alls + y.alls;
ret.maxs = max(x.maxr + y.maxl, max(x.maxs, y.maxs));
ret.maxl = max(x.maxl, x.alls + y.maxl);
ret.maxr = max(y.maxr, y.alls + x.maxr);
return ret;
}
void build(int cur, int f, int t)
{
if (f == t)
{
int x;
scanf("%d", &x);
d[cur] = data(x);
return;
}
int mid = f + t >> 1;
build(lc, f, mid);
build(rc, mid + 1, t);
d[cur] = update(d[lc], d[rc]);
}
data query(int cur, int f, int t, int qf, int qt)
{
if (qf <= f && t <= qt)
return d[cur];
data x(-INF), y(-INF);
x.alls = y.alls = 0;
int mid = f + t >> 1;
if (qf <= mid)
x = query(lc, f, mid, qf, qt);
if (qt > mid)
y = query(rc, mid + 1, t, qf, qt);
return update(x, y);
}
} it;
int main()
{
int n, m;
scanf("%d", &n);
it.build(1, 1, n);
scanf("%d", &m);
while (m --)
{
int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", it.query(1, 1, n, x, y).maxs);
}
return 0;
}