和I相比有了单点更新,所以不能只记录一个前缀和,而是要在线段树上多维护一个sum,表示这个结点的区间和,然后其他的就和I一样了。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 50001;
int a[N];
struct Node
{
int l, r, sum;
int maxl, maxr, maxn;
} node[N << 2];
void pushup( int i )
{
int lc = i << 1, rc = lc | 1;
node[i].sum = node[lc].sum + node[rc].sum;
node[i].maxl = max( node[lc].maxl, node[lc].sum + node[rc].maxl );
node[i].maxr = max( node[rc].maxr, node[rc].sum + node[lc].maxr );
node[i].maxn = max( node[lc].maxn, node[rc].maxn );
node[i].maxn = max( node[i].maxn, node[lc].maxr + node[rc].maxl );
}
void build( int i, int l, int r )
{
node[i].l = l, node[i].r = r;
if ( l == r )
{
node[i].sum = node[i].maxl = node[i].maxr = node[i].maxn = a[l];
return ;
}
int lc = i << 1, rc = lc | 1, mid = ( l + r ) >> 1;
build( lc, l, mid );
build( rc, mid + 1, r );
pushup(i);
}
void update( int i, int pos, int val )
{
if ( node[i].l == pos && node[i].r == pos )
{
node[i].sum = node[i].maxl = node[i].maxr = node[i].maxn = val;
return ;
}
int mid = ( node[i].l + node[i].r ) >> 1;
if ( pos <= mid )
{
update( i << 1, pos, val );
}
else
{
update( i << 1 | 1, pos, val );
}
pushup(i);
}
Node query( int i, int l, int r )
{
if ( node[i].l == l && node[i].r == r )
{
return node[i];
}
int lc = i << 1, rc = lc | 1, mid = ( node[i].l + node[i].r ) >> 1;
if ( r <= mid )
{
return query( lc, l, r );
}
else if ( l > mid )
{
return query( rc, l, r );
}
else
{
Node ln = query( lc, l, mid ), rn = query( rc, mid + 1, r ), res;
res.sum = ln.sum + rn.sum;
res.maxl = max( ln.maxl, ln.sum + rn.maxl );
res.maxr = max( rn.maxr, rn.sum + ln.maxr );
res.maxn = max( ln.maxn, rn.maxn );
res.maxn = max( res.maxn, ln.maxr + rn.maxl );
return res;
}
}
int main ()
{
int n, m;
while ( scanf("%d", &n) != EOF )
{
for ( int i = 1; i <= n; i++ )
{
scanf("%d", a + i);
}
build( 1, 1, n );
scanf("%d", &m);
while ( m-- )
{
int op, x, y;
scanf("%d%d%d", &op, &x, &y);
if ( op == 0 )
{
update( 1, x, y );
}
else
{
Node tmp = query( 1, x, y );
printf("%d\n", tmp.maxn);
}
}
}
return 0;
}