zoukankan      html  css  js  c++  java
  • [APIO 2014] 序列分割

    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=3675

    [算法]

             首先 , 我们发现将一段序列切成若干段所获得的收益与顺序无关

             于是我们可以用fi,j表示切i次 , 前j个数的最大收益

             令sumi表示ai的前缀和

             显然 , fi,j = max{ fi-1,k + sumk * (sumj - sumk) }

             斜率优化即可

             此题内存限制较紧 , 可以使用滚动数组优化空间复杂度

             时间复杂度 : O(NK)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 100010
    #define MAXK 210
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    int n , k , l , r;
    ll X[MAXN] , Y[MAXN] , sum[MAXN] , f[2][MAXN];
    int a[MAXN] , q[MAXN] , last[MAXK][MAXN];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    int main()
    {
            
            read(n); read(k);
            for (int i = 1; i <= n; i++)
            {
                    read(a[i]);
                    sum[i] = sum[i - 1] + a[i];
            }
            for (int i = 1; i <= k; i++)
            {
                    int now = i & 1 , pre = now ^ 1;
                    f[now][q[l = r = 1] = 0] = 0;
                    for (int j = 1; j <= n; j++)
                    {
                            while (l < r && Y[q[l + 1]] - Y[q[l]] >= -sum[j] * (X[q[l + 1]] - X[q[l]])) ++l;
                            f[now][j] = Y[q[l]] + X[q[l]] * sum[j];
                            X[j] = sum[j];
                            Y[j] = f[pre][j] - sum[j] * sum[j];
                            last[i][j] = q[l];
                            while (l < r && (Y[j] - Y[q[r]]) * (X[q[r]] - X[q[r - 1]]) >= (Y[q[r]] - Y[q[r - 1]]) * (X[j] - X[q[r]])) --r;
                            q[++r] = j; 
                    }        
            }
            printf("%lld
    " , f[k & 1][n]);
            int now = n , s = k;
            vector< int > ans;
            while (now > 0)
            {
                    now = last[s][now];
                    if (now) ans.push_back(now);
                    --s;
            }
            reverse(ans.begin() , ans.end());
        
            // 输出方案...
    
            return 0;
        
    }
  • 相关阅读:
    数据预处理
    数据挖掘-聚类分析
    数据挖掘分类--判别式模型 ----支持向量机
    神经网络
    数据挖掘-贝叶斯定理
    数据挖掘之分类和预测
    关于stm32的IO口的封装
    星际炸弹——炸弹爆炸时间计算
    共阳极数码管三极管驱动
    自定义的TIME.H头文件
  • 原文地址:https://www.cnblogs.com/evenbao/p/10354216.html
Copyright © 2011-2022 走看看