SPOJ GSS1_Can you answer these queries I(线段树区间合并)
标签(空格分隔): 线段树区间合并
题目链接
GSS1 - Can you answer these queries I
You are given a sequence A1, 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
题意:
求连续自区间最大和
题解:
线段树的区间合并可以解决有关连续子区间最值的问题,介绍一下,每一个节点都保存一个此区间的子区间最大值,那么在区间合并的时候就会遇到如何处理包含断点子区间的问题,我们用一个lv保存从左端点开始的连续子区间最值,用rv保存从到右端点结束的连续子区间最值,v表示整个区间的所有元素和,ans表示这个区间的连续子区间的最值。
那么有合并的时候v要考虑从左孩子的右端点结束加上右孩子的左端点开始,和左孩子和右孩子的ans最大值
lv要考虑的是左孩子的左端点开始或者是整个左孩子的所有值加上右孩子的从左端点开始的值
同样rv要考虑的是右孩子的右端点结束或者是整个右孩子的所有值加上左孩子的右端点结束的值
参考代码如下
void Push(int d){
st[d].v = st[lc].v+st[rc].v;
st[d].lv = max(st[lc].lv,st[lc].v+st[rc].lv);
st[d].rv = max(st[rc].rv,st[rc].v+st[lc].rv);
st[d].ans = max(max(st[lc].ans,st[rc].ans),st[lc].rv+st[rc].lv);
return;
}
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 50008;
#define mid (l+r>>1)
#define lc d<<1
#define rc d<<1|1
struct Tr{
int v,lv,rv,ans;
}st[N<<2];
void Push(int d){
st[d].v = st[lc].v+st[rc].v;
st[d].lv = max(st[lc].lv,st[lc].v+st[rc].lv);
st[d].rv = max(st[rc].rv,st[rc].v+st[lc].rv);
st[d].ans = max(max(st[lc].ans,st[rc].ans),st[lc].rv+st[rc].lv);
return;
}
void build(int l, int r, int d){
if(l==r){
scanf("%d",&st[d].ans);
st[d].v = st[d].lv = st[d].rv = st[d].ans;
return;
}
build(l,mid,lc);
build(mid+1,r,rc);
Push(d);
}
Tr query(int L, int R, int l, int r, int d)
{
if(l==L&&R==r){
return st[d];
}
else if(R<=mid) return query(L,R,l,mid,lc);
else if(L>mid) return query(L,R,mid+1,r,rc);
Tr la = query(L,mid,l,mid,lc);
Tr ra = query(mid+1,R,mid+1,r,rc);
Tr re;
re.v = la.v+ra.v;
re.lv = max(la.lv,la.v+ra.lv);
re.rv = max(ra.rv,ra.v+la.rv);
re.ans = max(max(ra.ans,la.ans),la.rv+ra.lv);
return re;
}
int main()
{
int n,m;
int ll,rr;
while(~scanf("%d",&n))
{
build(1,n,1);
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&ll,&rr);
Tr fn = query(ll,rr,1,n,1);
printf("%d\n",fn.ans);
}
}
return 0;
}