题意
见之前
思路
考虑动态规划求最大子段和。
设
f
i
f_i
fi为以
a
i
a_i
ai结尾的最大子段和,
g
i
g_i
gi为
a
i
a_i
ai前的最大子段和,得出方程:
f
i
=
m
a
x
(
f
i
−
1
+
a
i
,
a
i
)
、
g
i
=
m
a
x
(
g
i
−
1
,
f
i
)
f_i=max(f_{i-1}+a_i,a_i)、g_i=max(g_{i-1},f_i)
fi=max(fi−1+ai,ai)、gi=max(gi−1,fi)
将矩阵乘法运算改变,可以将方程改成矩阵乘法:
对于每个
a
i
a_i
ai都有一个矩阵
G
i
G_i
Gi,计算答案时用
G
l
G_l
Gl乘到
G
r
G_r
Gr,对于修改就直接把矩阵修改即可,线段树维护。
这就原来就是动态
d
p
dp
dp的入门了。。
代码
#include<cstdio>
#include<climits>
#include<cstring>
#include<algorithm>
const int inf = INT_MAX >> 1;//÷2不然加起来会爆炸
struct matrix {
int a[4][4];
};
struct SegmentTree {
int l, r;
matrix dat;
}t[200001];
int n, m;
int a[50001];
matrix operator *(const matrix &a, const matrix &b){
matrix c;
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
c.a[i][j] = -inf;
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
for (int k = 1; k <= 3; k++)
c.a[i][j] = std::max(c.a[i][j], a.a[i][k] + b.a[k][j]);
return c;
}
void build(int p, int l, int r) {
t[p].l = l;
t[p].r = r;
if (l == r) {
t[p].dat.a[1][1] = t[p].dat.a[1][3] = t[p].dat.a[2][1] = t[p].dat.a[2][3] = a[l];
t[p].dat.a[1][2] = t[p].dat.a[3][1] = t[p].dat.a[3][2] = -inf;
t[p].dat.a[2][2] = t[p].dat.a[3][3] = 0;
return;
}
int mid = l + r >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
t[p].dat = t[p << 1].dat * t[p << 1 | 1].dat;
}
matrix query(int p, int l, int r) {
if (l <= t[p].l && t[p].r <= r)
return t[p].dat;
int mid = t[p].l + t[p].r >> 1;
if (l <= mid && r > mid) return query(p << 1, l, r) * query(p << 1 | 1, l, r);
else if (l <= mid) return query(p << 1, l, r);
else if (r > mid) return query(p << 1 | 1, l, r);
}
void modify(int p, int pos, int val) {
if (t[p].l == t[p].r) {
t[p].dat.a[1][1] = t[p].dat.a[1][3] = t[p].dat.a[2][1] = t[p].dat.a[2][3] = val;
return;
}
int mid = t[p].l + t[p].r >> 1;
if (pos <= mid) modify(p << 1, pos, val);
else modify(p << 1 | 1, pos, val);
t[p].dat = t[p << 1].dat * t[p << 1 | 1].dat;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, 1, n);
scanf("%d", &m);
for (int op, x, y; m; m--) {
scanf("%d %d %d", &op, &x, &y);
if (op) {
matrix res = query(1, x, y);
printf("%d\n", std::max(res.a[2][1], res.a[2][3]));
}
else modify(1, x, y);
}
}