给定一个长度为 n n 的序列 ,会进行 m m 次操作,每次操作为以下两种操作之一:
1. 将 赋值为 val v a l ;
2. 询问区间 [l,r] [ l , r ] 的最多 k k 段不相交的序列之和的最大值。
(, |ai|,|val|≤500 | a i | , | v a l | ≤ 500 , k≤20 k ≤ 20 )
奇奇怪怪的分块做法,不知道为什么能过,复杂度 O(mn−−√k2) O ( m n k 2 )
#include <cstdio>
#include <cstring>
#include <cmath>
#define Min(_A, _B) (_A < _B ? _A : _B)
#define Max(_A, _B) (_A > _B ? _A : _B)
#define R register
int n, m, a[100010], f[555][22][2], g[555][22][2], h[22][2], e[2][22][2];
int block, u[100010];
void Build(R int t)
{
R int l = Max(t * block, 1), r = Min((t + 1) * block - 1, n);
for(R int i = 0; i <= 20; ++i) f[t][i][0] = f[t][i][1] = 0;
for(R int i = l; i <= r; ++i)
{
for(R int j = 0; j <= 20; ++j) h[j][0] = f[t][j][0], h[j][1] = f[t][j][1];
for(R int u = 0; u <= 20; ++u)
{
f[t][u][0] = Max(h[u][0], h[u][1]) + a[i];
if(u) f[t][u][1] = Max(h[u - 1][0], h[u][1]);
else f[t][u][1] = h[u][1];
}
}
f[t][0][1] = -1e9;
for(R int j = 0; j <= 20; ++j) g[t][j][0] = g[t][j][1] = a[l];
for(R int i = l + 1; i <= r; ++i)
{
for(R int j = 0; j <= 20; ++j) h[j][0] = g[t][j][0], h[j][1] = g[t][j][1];
for(R int u = 0; u <= 20; ++u)
{
if(u) g[t][u][0] = Max(h[u][0], h[u][1]) + a[i];
else g[t][u][0] = h[u][0] + a[i];
if(u) g[t][u][1] = Max(h[u - 1][0], h[u][1]);
else g[t][u][1] = Max(h[u][1], h[u][0]);
}
}
g[t][0][1] = -1e9;
}
int main()
{
scanf("%d", &n);
for(R int i = 1; i <= n; ++i) scanf("%d", &a[i]);
block = sqrt(n);
for(R int i = 1; i <= n; ++i) u[i] = i / block;
for(R int i = 0; i <= u[n]; ++i) Build(i);
scanf("%d", &m);
while(m--)
{
R bool opt; scanf("%d", &opt);
if(opt == 0)
{
R int pos, val; scanf("%d %d", &pos, &val);
a[pos] = val;
Build(u[pos]);
}
else
{
R int l, r, k; scanf("%d %d %d", &l, &r, &k);
R int d = 0;
for(R int i = 0; i <= k; ++i) e[d][i][0] = e[d][i][1] = 0;
for(R int i = l; u[l] == u[i] && i <= r; ++i)
{
d ^= 1;
for(R int u = 0; u <= k; ++u)
{
e[d][u][0] = Max(e[d ^ 1][u][0], e[d ^ 1][u][1]) + a[i];
if(u) e[d][u][1] = Max(e[d ^ 1][u - 1][0], e[d ^ 1][u][1]);
else e[d][u][1] = e[d ^ 1][u][1];
}
}
for(R int i = u[l] + 1; i < u[r]; ++i)
{
d ^= 1;
for(R int j = 0; j <= k; ++j) e[d][j][0] = e[d][j][1] = 0;
for(R int j = 0; j <= k; ++j)
{
for(R int l = 0; l + j <= k; ++l)
{
e[d][l + j][0] = Max(e[d][l + j][0], e[d ^ 1][l][1] + f[i][j][0]);
e[d][l + j][1] = Max(e[d][l + j][1], e[d ^ 1][l][1] + f[i][j][1]);
e[d][l + j + 1][0] = Max(e[d][l + j + 1][0], e[d ^ 1][l][0] + f[i][j][0]);
e[d][l + j + 1][1] = Max(e[d][l + j + 1][1], e[d ^ 1][l][0] + f[i][j][1]);
e[d][l + j][0] = Max(e[d][l + j][0], e[d ^ 1][l][0] + g[i][j][0]);
e[d][l + j][1] = Max(e[d][l + j][1], e[d ^ 1][l][0] + g[i][j][1]);
}
e[d][j][1] = Max(e[d][j][1], e[d ^ 1][j][1]);
if(j) e[d][j][1] = Max(e[d][j][1], e[d ^ 1][j - 1][0]);
}
}
if(u[l] != u[r])
{
for(R int i = u[r] * block; i <= r; ++i)
{
d ^= 1;
for(R int u = 0; u <= k; ++u)
{
e[d][u][0] = Max(e[d ^ 1][u][0], e[d ^ 1][u][1]) + a[i];
if(u) e[d][u][1] = Max(e[d ^ 1][u - 1][0], e[d ^ 1][u][1]);
else e[d][u][1] = e[d ^ 1][u][1];
}
}
}
R int Ans = 0;
for(R int i = 0; i < k; ++i) Ans = Max(Ans, Max(e[d][i][0], e[d][i][1]));
Ans = Max(e[d][k][1], Ans);
printf("%d\n", Ans);
}
}
return 0;
}