[题目描述1] 题目描述2
这两道题几乎一模一样,都是线段树实现单点修改,查询区间最大字段和的功能
这类题目的难点通常在于如何 p u s h u p pushup pushup 和 p u s h d o w n pushdown pushdown(这题因为是单点修改没有 p u s h d o w n pushdown pushdown)
先说一句废话一个区间的最大字段和有三种情况: 它左区间的最大字段和,它右区间的最大字段和,它左区间取一部分和它右区间取一部分
前两种情况pushup都非常好实现,现在只剩第三种了。我们可以对于线段树的一个节点可以维护以下的值,这样就能实现pushuup了:
sum:该区间的值
lsum:以该区间左端点为起点的最大字段和
rsum:以该区间右端点为终点的最大字段和
max_sum:该区间的最大字段和
不难发现,上述的第三种情况就变成了:左区间的
r
s
u
m
rsum
rsum + 右区间的
l
s
u
m
lsum
lsum
这样一来我们就可以写下本题的pushup了:
当前区间的 s u m sum sum = 左区间的 s u m sum sum + 右区间的 s u m sum sum(这个不用解释吧)
当前区间的 l s u m lsum lsum = max(左区间的 l s u m lsum lsum,左区间的 s u m sum sum + 右区间的 l s u m lsum lsum)
(自己画画图就明白了)
当前区间的 r s u m rsum rsum = max(右区间的 r s u m rsum rsum,右区间的 s u m sum sum + 左区间的 s u m sum sum)
(与上面同理)
当前区间的 m a x max max s u m sum sum = max(左区间的 m a x max max s u m sum sum,右区间的 m a x max max_ s u m sum sum,左区间的 r s u m rsum rsum + 右区间的 l s u m lsum lsum)
有了这个我们的程序就大功告成了
附上小白逛公园的代码(另一道题几乎一模一样,主程序部分稍加调整就行了)
# include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
const int inf = INT_MAX;
#define ll long long
#define FOR(i,a,b) for(int i = a;i <= b;i++)
#define _FOR(i,a,b) for(int i = a;i >= b;i--)
#define l(x) x << 1
#define r(x) x << 1 | 1
template<typename T> void read(T &x)
{
x = 0;int f = 1;
char c = getchar();
for(;!isdigit(c);c = getchar()) if(c == '-') f = -1;
for(;isdigit(c);c = getchar()) x = x * 10 + c - '0';
x *= f;
}
struct node
{
int l,r;
int sum,lsum,rsum,max_sum;
} t[N * 4];
int n,m;
int a[N];
void pushup(int p)
{
t[p].sum = t[l(p)].sum + t[r(p)].sum;
t[p].lsum = max(t[l(p)].lsum,t[l(p)].sum + t[r(p)].lsum);
t[p].rsum = max(t[r(p)].sum + t[l(p)].rsum,t[r(p)].rsum);
t[p].max_sum = max(max(t[l(p)].max_sum,t[r(p)].max_sum),t[l(p)].rsum + t[r(p)].lsum);
}
void build(int p,int l,int r)
{
t[p].l = l,t[p].r = r;
if(l == r)
{
t[p].lsum = t[p].rsum = t[p].max_sum = t[p].sum = a[l];
return ;
}
int mid = (l + r) >> 1;
build(l(p),l,mid);
build(r(p),mid + 1,r);
pushup(p);
}
void change(int p,int x,int y)
{
if(t[p].l == t[p].r)
{
t[p].lsum = t[p].rsum = t[p].max_sum = t[p].sum = y;
return ;
}
int mid = (t[p].l + t[p].r) >> 1;
if(x <= mid) change(l(p),x,y);
else change(r(p),x,y);
pushup(p);
}
node ask(int p,int l,int r)
{
if(l <= t[p].l && r >= t[p].r) return t[p];
int mid = (t[p].l + t[p].r) >> 1;
if(l <= mid && r <= mid) return ask(l(p),l,r);
else if(l > mid && r > mid) return ask(r(p),l,r);
else
{
node ans;
node x = ask(l(p),l,r),y = ask(r(p),l,r);
ans.sum = x.sum + y.sum;
ans.lsum = max(x.lsum,x.sum + y.lsum);
ans.rsum = max(y.sum + x.rsum,y.rsum);
ans.max_sum = max(max(x.max_sum,y.max_sum),x.rsum + y.lsum);
return ans;
}
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
read(n),read(m);
FOR(i,1,n)
read(a[i]);
build(1,1,n);
FOR(i,1,m)
{
int x,y,z;
read(x),read(y),read(z);
if(x == 2)
change(1,y,z);
else
{
if(y > z) swap(y,z);
printf("%d\n",ask(1,y,z).max_sum);
}
}
return 0;
}