SPOJ GSS3 (动态dp)
程序员文章站
2022-05-08 18:46:50
题意 "题目链接" Sol 这题可以动态dp做。 设$f[i]$表示以$i$为结尾的最大子段和,$g[i]$表示$1 i$的最大子段和 那么 $f[i] = max(f[i 1] + a[i], a[i])$ $g[i] = max(g[i 1], f[i])$ 发现只跟前一项有关,而且$g[i]从 ......
题意
sol
这题可以动态dp做。
设\(f[i]\)表示以\(i\)为结尾的最大子段和,\(g[i]\)表示\(1-i\)的最大子段和
那么
\(f[i] = max(f[i - 1] + a[i], a[i])\)
\(g[i] = max(g[i - 1], f[i])\)
发现只跟前一项有关,而且\(g[i]从\)f[i]$转移过来的那一项可以直接拆开
那么构造矩阵
\[ \begin{bmatrix} a_{i} & -\infty & \dots a_{i} \\ a_{i}, & 0 & a_{i}\\ -\infty, & -\infty & 0 \\ \end{bmatrix} \]
直接转移就行了
复杂度\(o(nlogn * 27)\)
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6 + 10, inf = 1e9; template<typename a, typename b> inline bool chmax(a &x, b y) {return x < y ? x = y, 1 : 0;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } struct ma { int m[4][4]; ma() { memset(m, -0x3f, sizeof(m)); } ma operator * (const ma &rhs) const { ma ans; for(int i = 1; i <= 3; i++) for(int j = 1; j <= 3; j++) for(int k = 1; k <= 3; k++) chmax(ans.m[i][j], m[i][k] + rhs.m[k][j]); return ans; } void init(int v) { m[1][1] = v; m[1][2] = -inf; m[1][3] = v; m[2][1] = v; m[2][2] = 0; m[2][3] = v; m[3][1] = -inf; m[3][2] = -inf; m[3][3] = 0; } }m[maxn]; int n, m, a[maxn]; #define ls k << 1 #define rs k << 1 | 1 void update(int k) { m[k] = m[ls] * m[rs]; } void build(int k, int l, int r) { if(l == r) {m[k].init(a[l]); return ;} int mid = l + r >> 1; build(ls, l, mid); build(rs, mid + 1, r); update(k); } void modify(int k, int l, int r, int p, int v) { if(l == r) {m[k].init(v); return ;} int mid = l + r >> 1; if(p <= mid) modify(ls, l, mid, p, v); else modify(rs, mid + 1, r, p, v); update(k); } ma query(int k, int l, int r, int ql, int qr) { if(ql <= l && r <= qr) return m[k]; int mid = l + r >> 1; if(ql > mid) return query(rs, mid + 1, r, ql, qr); else if(qr <= mid) return query(ls, l, mid, ql, qr); else return (query(ls, l, mid, ql, qr) * query(rs, mid + 1, r, ql, qr)); } int main() { n = read(); for(int i = 1; i <= n; i++) a[i] = read(); build(1, 1, n); m = read(); while(m--) { int opt = read(), x = read(), y = read(); if(opt == 0) modify(1, 1, n, x, y); else { ma ans = query(1, 1, n, x, y); printf("%d\n", max(ans.m[2][1], ans.m[2][3])); } } return 0; } /* 4 -1 -2 -3 -4 2 1 1 4 1 1 2 */
上一篇: 情侣一起健身更有效
下一篇: 瘦身操也有错 5盲点会越减越胖