「Codeforces 280D」k-Maximum Subsequence Sum

给定一个长度为 n 的序列 A ,会进行 m 次操作,每次操作为以下两种操作之一:
1. 将 a i 赋值为 v a l
2. 询问区间 [ l , r ] 的最多 k 段不相交的序列之和的最大值。
1 n , m 10 5 , | a i | , | v a l | 500 , k 20

奇奇怪怪的分块做法,不知道为什么能过,复杂度 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;
}

猜你喜欢

转载自blog.csdn.net/steaunk/article/details/80296296