SPOJ 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

对于线段树的一个结点,维护其总区间的最大序列,左起区间的最大序列(la),右起区间的最大序列(ra)。

虽然有一些思路,但是并没有那么好写,尤其是在刷了一天学校的题,大脑基本停转的时候。

改来改去改不对,最后抄了别人的题解。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<list>
using namespace std;
struct NODE{
	int l,r;
	int max,sum;//最大区间以及整个区间和 
	int ra,la;//左右字树的和 
}e[200000];
int data[200000];
int n,m;
void Build(int l,int r,int num){
	e[num].l=l;
	e[num].r=r;
	if(l==r){
		e[num].sum=data[l];
		e[num].max=data[l];
		e[num].ra=e[num].la=data[l];
		return;
	}
	int mid=(l+r)/2;
	Build(l,mid,num<<1);
	Build(mid+1,r,num*2+1);
	e[num].sum=e[num<<1].sum+e[num*2+1].sum;
	e[num].la=max(e[num<<1].la,e[num<<1].sum+e[num<<1].la);
	e[num].ra=max(e[num<<1].ra,e[num<<1].sum+e[num<<1].ra);
	e[num].max=max(e[num<<1].ra+e[num*2+1].la,max(e[num<<1].max,e[num*2+1].max));
	return;
}
NODE qu(int l,int r,int num){
	NODE node,n1,n2;
	if(e[num].r<=r && e[num].l>=l)return e[num];
	int mid=(e[num].l+e[num].r)/2;
	if(mid<l){
		n2=qu(l,r,num*2+1);
		return n2;
	}else if(mid>=r){
		n1=qu(l,r,num*2);
		return n1;
	}
	n1=qu(l,r,num*2);n2=qu(l,r,num*2+1);
	node.sum=n1.sum+n2.sum;	
	node.la=max(n1.la,n1.sum+n2.la);
	node.ra=max(n2.ra,n2.sum+n1.ra);
	node.max=max(n1.ra+n2.la,max(n1.max,n2.max));
	return node;
}
int main(){
	scanf("%d",&n);
	int i,j;
	for(i=1;i<=n;i++)scanf("%d",&data[i]);
	Build(1,n,1);
	scanf("%d",&m);
	int x,y;
	for(i=1;i<=m;i++){
		scanf("%d%d",&x,&y);
		NODE a=qu(x,y,1);
		printf("%d\n",a.max);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值