题目链接:https://cn.vjudge.net/problem/SPOJ-GSS3
题目大意:n个数,m次操作,0,x,y,表示把a[x]位置的数改为y,1,x,y,表示求[x,y]的最大连续子段和。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 50010;
int n, m;
ll a[N];
struct node{
int l, r;
ll ls, rs, ms,sum;
}tr[N<<2];
void pushup(int m)
{
tr[m].sum = tr[m<<1].sum + tr[m<<1|1].sum;
tr[m].ls = max(tr[m<<1].ls, tr[m<<1].sum + tr[m<<1|1].ls);
tr[m].rs = max(tr[m<<1|1].rs, tr[m<<1|1].sum + tr[m<<1].rs);
tr[m].ms = max(tr[m<<1].rs + tr[m<<1|1].ls, max(tr[m<<1].ms, tr[m<<1|1].ms));
}
void build(int m, int l, int r)
{
tr[m].l = l;
tr[m].r = r;
if(l == r)
{
tr[m].ls = tr[m].rs = tr[m].ms = tr[m].sum = a[l];
return ;
}
int mid = (l + r) >> 1;
build(m<<1, l, mid);
build(m<<1|1, mid + 1, r);
pushup(m);
}
void updata(int m, int id, ll val)
{
if(tr[m].l == id && tr[m].r == id)
{
tr[m].ls = tr[m].rs = tr[m].ms = tr[m].sum = val;
return ;
}
int mid = (tr[m].l + tr[m].r) >> 1;
if(id <= mid)
updata(m<<1, id, val);
else
updata(m<<1|1, id, val);
pushup(m);
}
node ask(int m, int l, int r)
{
if(tr[m].l == l && tr[m].r == r)
return tr[m];
int mid = (tr[m].l + tr[m].r) >> 1;
if(r <= mid)
return ask(m<<1, l, r);
else if(l > mid)
return ask(m<<1|1, l, r);
else
{
node a, b, c;
a = ask(m<<1, l, mid);
b = ask(m<<1|1, mid + 1, r);
c.sum = a.sum + b.sum;
c.ls = max(a.ls, a.sum + b.ls);
c.rs = max(b.rs, b.sum + a.rs);
c.ms = max(a.rs + b.ls, max(a.ms, b.ms));
return c;
}
}
int main()
{
while(~scanf("%d", &n))
{
for(int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
build(1, 1, n);
scanf("%d", &m);
int op;
while(m--)
{
scanf("%d", &op);
if(op == 0)
{
int x;
ll val;
scanf("%d %lld", &x, &val);
updata(1, x, val);
}
else
{
int l, r;
scanf("%d %d", &l, &r);
if(l > r)
swap(l, r);
node tmp = ask(1, l, r);
printf("%lld\n", tmp.ms);
}
}
}
return 0;
}