• bzoj3675 [Apio2014]序列分割


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3675

    http://uoj.ac/problem/104

    【题解】

    当时想的时候猜了下从前往后分比较优。

    后来证明了一下怎么分都一样。。可以把贡献式子拆开来分析。

    这样分析完就可以得到贡献=Σ每两个块的和的积

    那么我们整理可以得到贡献=Σ第i个块的和*(前面所有块的和)

    那么有dp: f[i,j]表示到第i块,选择的数是a[1]...a[j]的贡献max。

    那么直接dp有50分。

    # include <stdio.h>
    # include <string.h>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 1e5 + 10, N = 210;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, K, a[M];
    ll s[M], f[N][M];
    int pre[N][M];
    
    inline void prt(int i, int j) {
        if(i == 1) return;
        prt(i-1, pre[i][j]);
        printf("%d ", pre[i][j]);
    }
    
    int main() {
        scanf("%d%d", &n, &K);
        for (int i=1; i<=n; ++i) scanf("%d", &a[i]), s[i] = s[i-1] + a[i];
        for (int i=2; i<=K+1; ++i) 
            for (int j=1; j<=n; ++j) {
                f[i][j] = -1e18;
                for (int k=1; k<j; ++k) {
                    if(f[i][j] < f[i-1][k] + (s[j]-s[k])*s[k]) {
                        f[i][j] = f[i-1][k] + (s[j]-s[k])*s[k];
                        pre[i][j] = k;
                    }
                }
            }
        printf("%lld
    ", f[K+1][n]);
        prt(K+1, n);
        return 0;
    }
    View Code

    肯定不能直接dp,需要优化

    明显可斜率优化。

    直接上即可。

    uoj版本(输出方案,空间不限制)

    # include <stdio.h>
    # include <string.h>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 1e5 + 10, N = 210;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, K, a[M];
    ll s[M], f[N][M];
    int pre[N][M];
    int q[M], head, tail;
    
    inline void prt(int i, int j) {
        if(i == 1) return;
        prt(i-1, pre[i][j]);
        printf("%d ", pre[i][j]);
    }
    
    inline ll slop(int i, int k1, int k2) {
        return f[i-1][k1]-f[i-1][k2]+s[k2]*s[k2]-s[k1]*s[k1];
    }
    
    inline ll getdp(int i, int j, int x) {
        return f[i-1][x]+(s[j]-s[x])*s[x];
    }
    
    int main() {
        scanf("%d%d", &n, &K);
        for (int i=1; i<=n; ++i) scanf("%d", &a[i]), s[i] = s[i-1] + a[i];
        for (int i=2; i<=K+1; ++i) {
            head = 1, tail = 0;
            for (int j=1; j<=n; ++j) {
                while(head<tail && slop(i, q[head], q[head+1]) <= (s[q[head+1]] - s[q[head]]) * s[j]) ++head;
                f[i][j] = getdp(i, j, q[head]);
                pre[i][j] = q[head];
                while(head<tail && slop(i, q[tail-1], q[tail]) * (s[j] - s[q[tail]]) >= slop(i, q[tail], j) * (s[q[tail]] - s[q[tail-1]])) --tail;
                q[++tail] = j;
            }
        }
        printf("%lld
    ", f[K+1][n]);
        prt(K+1, n);
        return 0;
    }
    View Code

    bzoj版本(不输出方案,空间限制)

    # include <stdio.h>
    # include <string.h>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 1e5 + 10, N = 210;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, K, a[M];
    ll s[M], f[2][M];
    int q[M], head, tail;
    int pre, cur;
    
    inline ll slop(int k1, int k2) {
        return f[pre][k1]-f[pre][k2]+s[k2]*s[k2]-s[k1]*s[k1];
    }
    
    inline ll getdp(int j, int x) {
        return f[pre][x]+(s[j]-s[x])*s[x];
    }
    
    int main() {
        scanf("%d%d", &n, &K);
        for (int i=1; i<=n; ++i) scanf("%d", &a[i]), s[i] = s[i-1] + a[i];
        pre = 0, cur = 1;
        for (int i=2; i<=K+1; ++i) {
            head = 1, tail = 0;
            for (int j=1; j<=n; ++j) {
                while(head<tail && slop(q[head], q[head+1]) <= (s[q[head+1]] - s[q[head]]) * s[j]) ++head;
                f[cur][j] = getdp(j, q[head]);
                while(head<tail && slop(q[tail-1], q[tail]) * (s[j] - s[q[tail]]) >= slop(q[tail], j) * (s[q[tail]] - s[q[tail-1]])) --tail;
                q[++tail] = j;
            }
            swap(pre, cur);
        }
        printf("%lld
    ", f[pre][n]);
        return 0;
    }
    View Code
  • 相关阅读:
    出现Invalid input of type: 'CacheKey'. Convert to a byte, string or number first
    如果错误发生在某个封装号的模块中,那请查看数据库里面的数据是不是哪里出现问题
    发现匿名用户问题
    关于序列化器中class Meta中属性说明
    序列化和反序列化
    前端出现has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
    出现bad ruqest,查找原因思路
    注册验证出现错误Define UserView.model, UserView.queryset, or override UserView.get_queryset()
    跨域问题
    celery异步使用和启动方法
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3675.html
Copyright © 2020-2023  润新知