You are given a sequence A of N (N <= 50000) integers between -10000 and 10000. On this sequence you have to apply M (M <= 50000) operations:
modify the i-th element in the sequence or for given x y print max{Ai + Ai+1 + … + Aj | x<=i<=j<=y }.
Input
The first line of input contains an integer N. The following line contains N integers, representing the sequence A1…AN.
The third line contains an integer M. The next M lines contain the operations in following form:
0 x y: modify Ax into y (|y|<=10000).
1 x y: print max{Ai + Ai+1 + … + Aj | x<=i<=j<=y }.
Output
For each query, print an integer as the problem required.
Example
Input:
4
1 2 3 4
4
1 1 3
0 3 -3
1 2 4
1 3 3
Output:
6
4
-3
求区间最大子段和。
学过求整个区间最大子段和的问题,O(n)的时间复杂度扫过一遍就行。
但是求一段区间内的就很麻烦。我们学过的数据结构就是来优化算法的。线段树就派上用场了。
(真的很佩服把这些算法想出来的人)
线段树维护四个值。
1.区间靠近左端点的最大子段和值。
2.区间靠近右端点的最大子段和值。
3.整个区间的总值。
4.整个区间的最大子段和值。
①维护靠近左端点的最大子段和值,有两个来源:左儿子的lmax,左儿子的msum+右儿子的lmax。
②维护靠近右端点的最大子段和值,有两个来源,右儿子的rmax,右儿子的msum+左儿子的rmax。
③维护整个区间的最大子段和值,有三个来源,左儿子的msum,右儿子的msum,左儿子的rmax+右儿子的lmax。
④维护整个区间的总值。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxx=1e5+100;
struct node{
int l;
int r;
int msum;
int lsum;
int rsum;
int sum;
}p[maxx<<2];
int a[maxx];
int n,m,L,R,ans;
inline int read()
{
char ch = getchar(); int x = 0, f = 1;
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
} while('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
} return x * f;
}
inline void pushup(int cur)
{
p[cur].sum=p[cur<<1].sum+p[cur<<1|1].sum;
p[cur].msum=max(max(p[cur<<1].msum,p[cur<<1|1].msum),p[cur<<1|1].lsum+p[cur<<1].rsum);
p[cur].lsum=max(p[cur<<1].lsum,p[cur<<1|1].lsum+p[cur<<1].sum);
p[cur].rsum=max(p[cur<<1|1].rsum,p[cur<<1].rsum+p[cur<<1|1].sum);
}
inline void build(int l,int r,int cur)
{
p[cur].l=l;
p[cur].r=r;
p[cur].lsum=p[cur].rsum=p[cur].msum=p[cur].sum=0;
if(l==r)
{
a[l]=read();
p[cur].lsum=p[cur].rsum=p[cur].msum=p[cur].sum=a[l];
return ;
}
int mid=l+r>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
pushup(cur);
}
inline void update(int pos,int v,int cur)
{
int L=p[cur].l;
int R=p[cur].r;
if(L==R)
{
p[cur].sum=p[cur].lsum=p[cur].rsum=p[cur].msum=v;
return ;
}
int mid=L+R>>1;
if(pos<=mid) update(pos,v,cur<<1);
else update(pos,v,cur<<1|1);
pushup(cur);
}
inline node query(int l,int r,int cur)
{
int LL=p[cur].l;
int RR=p[cur].r;
if(l<=LL&&RR<=r) return p[cur];
int mid=LL+RR>>1;
node lll,rr,ans;
if(r<=mid) return query(l,r,cur<<1);
else if(l>mid) return query(l,r,cur<<1|1);
else
{
lll=query(l,mid,cur<<1);
rr=query(mid+1,r,cur<<1|1);
ans.sum=lll.sum+rr.sum;
ans.msum=max(max(lll.msum,rr.msum),lll.rsum+rr.lsum);
ans.lsum=max(lll.lsum,lll.sum+rr.lsum);
ans.rsum=max(rr.rsum,rr.sum+lll.rsum);
return ans;
}
}
int main()
{
int op,l,r;
while(~scanf("%d",&n))
{
build(1,n,1);
m=read();
while(m--)
{
op=read(),l=read(),r=read();
if(op==0) update(l,r,1);
else
{
ans=-inf;
L=R=0;
node ans=query(l,r,1);
printf("%d\n",ans.msum);
}
}
}
return 0;
}
努力加油a啊,(o)/~