SPOJ GSS1 Can you answer these queries I

GSS1 - Can you answer these queries I


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

【题目分析】
乍一看是一个挺裸的线段树的题,然后花了30分钟写完。然后开始了一个小时漫长的交题记录,前前后后交了20多次,最后才发现自己的nowl,nowr,now写成了全局变量,然后各种迷之错误 RE+WA 。直到一个小时之后才改对。
说一下这道题的思路 用线段树去维护一个区间的最大序列,最大的从左端开始的序列,最大的从右端开始的序列,以及和。
那么每次在一个节点处准备合并两个儿子的时候,首先,最大从左的序列就等于max(lch.lans,lch.sum+rch.lans)因为区间的覆盖可能是只有左半部分或者横跨左右两部分。
那么从右端开始也是一样的。最大的子序列和就等于自身从左或从右或者两个儿子中间出现的那一部分,然后计算一下。
小技巧,利用结构体的返回值进行计算会更好。
综上所述,写题时一定要认真。QAQ
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#define F(i,j,k) for (int i=j;i<=k;++i)
#define LOW -600000000
using namespace std;
struct node{
	int l,r,sum,lans,rans,max;
}t[401000];
int data[50010];
int n,q;
void build(int l,int r,int num)
{
	t[num].l=l;
	t[num].r=r;
	if (l==r){
		t[num].lans=t[num].rans=t[num].max=t[num].sum=data[l];
		return;
	}
	build(l,(l+r)/2,num*2);
	build((l+r)/2+1,r,num*2+1);
	t[num].sum=t[num*2].sum+t[num*2+1].sum;
	t[num].lans=max(t[num*2].lans,t[num*2].sum+t[num*2+1].lans);
	t[num].rans=max(t[num*2+1].rans,t[num*2+1].sum+t[num*2].rans);
	t[num].max=max(t[num*2].rans+t[num*2+1].lans,max(t[num*2].max,t[num*2+1].max));

}
node find(int l,int r,int num)
{
	node now,nowl,nowr;
	if (t[num].r<=r&&t[num].l>=l) return t[num];
	int mid=(t[num].l+t[num].r)/2;
	if (mid<l) {nowr=find(l,r,num*2+1);
		return nowr;
	}
	else if (mid>=r){
	nowl=find(l,r,num*2);
		return nowl;
	}
	nowl=find(l,r,num*2);
	nowr=find(l,r,num*2+1);
	now.sum=nowl.sum+nowr.sum;
	now.lans=max(nowl.lans,nowl.sum+nowr.lans);
	now.rans=max(nowr.rans,nowr.sum+nowl.rans);
	now.max=max(nowl.rans+nowr.lans,max(nowl.max,nowr.max));
	return now;
}
int main()
{
	scanf("%d",&n);
	F(i,1,n) scanf("%d",&data[i]);
	build(1,n,1);
	scanf("%d",&q);
	F(i,1,q){
		int x,y;
		scanf("%d%d",&x,&y);
		printf("%d\n",find(x,y,1).max);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值