[SPOJ] 1043 Can you answer these queries I [GSS1]
Pro
给你一个序列{A[1], A[2], ..., A[N]}.( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 )
给定“查询”操作的定义如下:
Query(x,y) = Max { a[i]+a[i+1]+...+a[j] ; x ≤ i ≤ j ≤ y }.
给出M个查询,你的程序需要输出这些查询的结果。
Input
输入文件的第一行包含一个整数n,表示给出的数的个数;
在第二行,给出N个数字,表示A[1]到A[n];
第三行包含整数M,表示询问的个数;
接下来M行,每行包含两个数x和y.
Output
你的程序应该输出M个查询的结果,每个查询结果占一行。
Sample Input
3
-1 2 3
1
1 2
Sample Output
2
Solution
这是一道比较基础的线段树的练习题,即询问区间最大字段和, 我们可以用线段树维护4个值,
分别是当前区间从最左端开始的最大子段lmax, 从最右端开始的最大子段rmax,当前区间的最大子段和smax以及当前区间的和sum。
对于每一个询问,我们可以在自底向上(zkw)的过程中维护3个值,
分别是 当前左区间从最右端开始的最大子段lrans,当前有区间从最左端开始的最大子段rlans,
还有当前左区间和右区间中的最大子段和subans,最后在lrans + rlans和subans中取 最大值输出就可以了。
Source
#include <stdio.h> #include <memory.h> const int nmax = 50000; int lmax[(1 << 17) + 18], rmax[(1 << 17) + 18], sum[(1 << 17) + 18], smax[(1 << 17) + 18]; int n, m, l, r, M = 1; int i, lrans, rlans, subans; int max (int a, int b) { return a > b ? a : b; } int query (int l, int r) { subans = lrans = rlans = -nmax; for (l += M - 1, r += M + 1; l ^ r ^ 1; l >>= 1, r >>= 1) { if (~l & 1) { subans = max (subans, max (smax[l ^ 1], lrans + lmax[l ^ 1])); lrans = max (rmax[l ^ 1], lrans + sum[l ^ 1]); } if ( r & 1) { subans = max (subans, max (smax[r ^ 1], rlans + rmax[r ^ 1])); rlans = max (lmax[r ^ 1], rlans + sum[r ^ 1]); } } return max (subans, lrans + rlans); } int main () { freopen ("GSS1.in", "r", stdin); freopen ("GSS1.out", "w", stdout); scanf ("%d", &n); memset (lmax, 0xEF, sizeof (lmax)); memset (rmax, 0xEF, sizeof (rmax)); memset (sum, 0xEF, sizeof (sum)); memset (smax, 0xEF, sizeof (smax)); while (M < n) M <<= 1; for (i = 1; i <= n; ++i) scanf ("%d", &lmax[i + M]), sum[i + M] = rmax[i + M] = smax[i + M] = lmax[i + M]; for (i = M - 1; i; --i) { lmax[i] = max (lmax[i << 1], sum[i << 1] + lmax[(i << 1) + 1]); rmax[i] = max (rmax[(i << 1) + 1], rmax[i << 1] + sum[(i << 1) + 1]); sum[i] = sum[i << 1] + sum[(i << 1) + 1]; smax[i] = max (max (smax[i << 1], smax[(i << 1) + 1]), rmax[i << 1] + lmax[(i << 1) + 1]); } scanf ("%d", &m); for (i = 1; i <= m; ++i) scanf ("%d%d", &l, &r), printf ("%d\n", query (l, r)); return 0; }