spoj GSS1

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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值