【单点修改 最大连续子段和】 Can you answer this question
传送门
题意
给定长度为\(n\)的序列\(a\),一共\(m\)条指令,每个指令有两种
- \((1,x,y)\) ,查询区间\([x,y]\)的最大子序列和
- \((2,x,y)\) ,将\(a[x]\)的值改成\(y\)
对于每个查询输出整数答案
数据范围
\(1\leq N \leq 500000\)
$ 1\leq M \leq 100000$
题意
维护的属性有
- \(mx\):当前区间内部的最大连续子段和
- \(lmax\):紧靠当前区间左端的最大连续子段和
- \(rmax\):紧靠当前区间右端的最大连续子段和
- \(sum\):当前区间和
当前节点的区间中最大连续和从三种情况中取得
- \(l.mx\)
- \(r.mx\)
- \(l.rmax+r.lmax\)
\(lmax\)从以下两种情况中取最大值
- \(lmax\)完全在左半边
- \(lmax\)是左边\(sum\)加右边\(lmax\)
\(rmax\)从以下两种情况中取最大值
- \(rmax\)完全在右半边
- \(rmax\)是左边的\(rmax\)加右边的\(sum\)
所以要维护一个\(sum\),便于计算左右的连续子段和
查询可能存在的坑点:左右端点相反
- \(build\)时就会将线段树的左端点划入区间的子段,所以在查询时递归进入左子树的需要取等号
Code
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i < n; i ++)
const int N = 5e5 + 10;
int n, m;
int a[N];
struct node
{
int l, r;
int sum;
int lmax, rmax;
int mx;
#define l(u) u * 2
#define r(u) u * 2 + 1
}tr[N * 4];
void pushup(node &root, node &left, node &right)
{
root.sum = left.sum + right.sum;
root.lmax = max(left.lmax, left.sum + right.lmax);
root.rmax = max(right.rmax, right.sum + left.rmax);
root.mx = max(max(left.mx, right.mx), left.rmax + right.lmax);
}
void pushup(int u)
{
pushup(tr[u], tr[l(u)], tr[r(u)]);
}
void build(int u, int l, int r)
{
if(l == r)
tr[u] = {l, r, a[l], a[l], a[l], a[l]};
else
{
tr[u].l = l; tr[u].r = r;
int mid = l + r >> 1;
build(l(u), l, mid);
build(r(u), mid + 1, r);
pushup(u);
}
}
void modify(int u, int x, int y)
{
if(tr[u].l == x && tr[u].r == x)
tr[u]={x, x, y, y, y, y};
else
{
int mid = tr[u].l + tr[u].r >> 1;
if(x <= mid) modify(l(u), x, y);
else modify(r(u), x, y);
pushup(u);
}
}
node query(int u, int l, int r)
{
if(tr[u].l >= l && tr[u].r <= r)
return tr[u];
int mid = tr[u].l + tr[u].r >> 1;
if(l > mid) return query(r(u), l, r);
if(r <= mid) return query(l(u), l, r);
else
{
node left = query(l(u), l, r);
node right = query(r(u), l, r);
node res;
pushup(res, left, right);
return res;
}
}
int main()
{
cin>>n>>m;
rep(i, 1, n+1) cin>>a[i];
build(1,1,n);
int op, x, y;
while(m --)
{
cin>>op>>x>>y;
if(op == 1)
{
if(x > y) swap(x, y);
cout<<query(1, x, y).mx<<endl;
}
else
modify(1, x, y);
}
}

浙公网安备 33010602011771号