题意翻译

\(n\) 个数,\(q\) 次操作

操作\(0\) \(x\) \(y\)\(A_x\) 修改为\(y\)

操作\(1\) \(l\) \(r\)询问区间\([l, r]\)的最大子段和

输入输出格式

输入格式:

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

输出格式:

For each query, print an integer as the problem required.

输入输出样例

输入样例#1:

4
1 2 3 4
4
1 1 3
0 3 -3
1 2 4
1 3 3

输出样例#1:

6
4
-3

思路:首先分析询问的本质:求出区间最大子段和!很显然我们可以使用线段树维护序列,本题的难点主要在如何进行上传操作,将子树\(l\)\(r\)的节点信息上传到子树\(rt\)时,对于\(rt\)维护的序列中,和最大的子段有两种情况:

  1. 子段不经过中点,那么 \(rt\) 的答案为 \(l\)\(r\) 的答案的最大值。
  2. 子段经过了中点。这种情况比较复杂,因为我们无法知道子树的答案所对应的序列。这也是本题的难点所在。

然后我们用结构体板线段树来分情况维护一下最大字段和即可,结构体传址快。

代码:

#include<cstdio>
#include<algorithm>
#include<cctype>
#define maxn 50007
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
inline int qread() {
  char c=getchar();int num=0,f=1;
  for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
  for(;isdigit(c);c=getchar()) num=num*10+c-'0';
  return num*f;
}
int n,m;
struct Tree {
  int lmax,rmax,sum,maxx;
}tree[maxn<<2];
inline void pushup(int rt) {
  tree[rt].lmax=max(tree[ls].lmax,tree[ls].sum+tree[rs].lmax);
  tree[rt].rmax=max(tree[rs].rmax,tree[rs].sum+tree[ls].rmax);
  tree[rt].maxx=max(tree[ls].rmax+tree[rs].lmax,max(tree[ls].maxx,tree[rs].maxx));
  tree[rt].sum=tree[ls].sum+tree[rs].sum;
}
void build(int rt, int l, int r) {
  if(l==r) {
    tree[rt].lmax=tree[rt].rmax=tree[rt].sum=tree[rt].maxx=qread();
    return;
  }
  int mid=(l+r)>>1;
  build(ls,l,mid);
  build(rs,mid+1,r);
  pushup(rt);
}
void add(int rt, int l, int r, int L, int val) {
  if(l==r) {
    tree[rt].lmax=tree[rt].rmax=tree[rt].sum=tree[rt].maxx=val;
    return;
  }
  int mid=(l+r)>>1;
  if(L<=mid) add(ls,l,mid,L,val);
  else add(rs,mid+1,r,L,val);
  pushup(rt);
}
Tree query(int rt, int l, int r, int L, int R) {
  if(L==l&&r==R) return tree[rt];
  int mid=(l+r)>>1;
  if(L>mid) return query(rs,mid+1,r,L,R);
  else if(R<=mid) return query(ls,l,mid,L,R);
  else {
    Tree a=query(ls,l,mid,L,mid),b=query(rs,mid+1,r,mid+1,R),c;
    c.lmax=max(a.lmax,a.sum+b.lmax);
    c.rmax=max(b.rmax,b.sum+a.rmax);
    c.sum=a.sum+b.sum;
    c.maxx=max(a.rmax+b.lmax,max(a.maxx,b.maxx));
    return c;
  }
}
int main() {
  n=qread();
  build(1,1,n);
  m=qread();
  for(int i=1,k,x,y;i<=m;++i) {
    k=qread(),x=qread(),y=qread();
    if(!k) add(1,1,n,x,y);
    else printf("%d\n",query(1,1,n,x,y).maxx);
  }
  return 0;
}