题目大意

让你把一个数列分成k+1个部分,使分成乘积分成各个段乘积和最大。

分析

首先肯定是无法开下n \(\times\) n的数组,那么来一个小技巧:因为我们知道k的状态肯定是从k-1的状态转移过来的,而且只从k-1的状态转移过来,那么我们就记录一下k-1和k的状态。
然后我们再来动态规划:
状态肯定是:\(f[i]\)表示前i个数,分成j段(j枚举,滚动数组优化成n)。
转移方程就是:
\[f[i]=max(g[j]+sum[j]\times(sum[i]-sum[k]))\]
一开始看错题目了,以为是乘积的乘积最大,而且是各个段的。一直过不了样例。
那么以上的转移方程就可以拿到一小部分分数了。


以下是斜率优化的部分:
按照斜率优化的套路,首先假设j>k,且j的状态比k要优。
那么得到了式子:
\[g[j]+sum[j]\times(sum[i]-sum[j])>g[k]+sum[k]\times(sum[i]-sum[k])\]
化简就得到了以下的不等式:(初中知识就可以了)

\[\frac{(g[j]-sum[j]^2)-(g[k]-sum[k]^2)}{sum[k]-sum[j]}<=sum[i]\]

那么单调队列维护凸包就可以了。

开了o2卡了常才过掉的垃圾代码

// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define N 100005
#define ll long long
#define db double
using namespace std;
ll g[N][255], f[N], dp[N], sum[N], a[N];
int n, m;
int q[N], ans[N];
template <typename T>
inline void read(T &x) {
    x = 0; T fl = 1;
    char ch = 0;
    while (ch < '0' || ch > '9') {
        if (ch == '-') fl = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    x *= fl;
}
ll X(int i) {
    return sum[i];
}
ll Y(int i) {
    return f[i] - sum[i] * sum[i];
}
db slope(int i, int j) {
    if (sum[i] == sum[j]) return - 1e18;
    return ((1.0 * (Y(i) - Y(j))) / (1.0 * (X(j) - X(i))));
}
int main() {
    read(n); read(m);
    for (int i = 1; i <= n; i ++) {
        read(a[i]);
        sum[i] = sum[i - 1] + a[i];
    }
    for (int j = 1; j <= m; j ++) {
        int h = 0, t = 0;
        for (int i = 1; i <= n; i ++) {
            while (h < t && slope(q[h], q[h + 1]) <= sum[i]) ++ h;
            int k = q[h];
            dp[i] = f[k] + sum[k] * (sum[i] - sum[k]);
            g[i][j] = k;
            while (h < t && slope(q[t - 1], q[t]) >= slope(q[t], i)) -- t;
            q[++ t] = i;
        }
        for (int i = 1; i <= n; i ++) f[i] = dp[i];
    }
    printf("%lld\n", dp[n]);
    int tot = 0;
    for (int x = n, i = m; i >= 1; i --) {
        x = g[x][i];
        ans[++ tot] = x;
    }
    for (int i = tot; i >= 1; i --) printf("%d ", ans[i]);
    return 0;
}

[luogu3648][bzoj3675][APIO2014]序列分割【动态规划+斜率优化】的更多相关文章

  1. BZOJ3675 [Apio2014]序列分割 动态规划 斜率优化

    原文链接http://www.cnblogs.com/zhouzhendong/p/8697258.html 题目传送门 - BZOJ3675 题意 对于一个非负整数序列,小H需要重复k次以下的步骤: ...

  2. [Bzoj3675][Apio2014]序列分割(斜率优化)

    3675: [Apio2014]序列分割 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 4021  Solved: 1569[Submit][Stat ...

  3. BZOJ3675 [Apio2014]序列分割 【斜率优化dp】

    3675: [Apio2014]序列分割 Time Limit: 40 Sec  Memory Limit: 128 MB Submit: 3366  Solved: 1355 [Submit][St ...

  4. 2018.09.29 bzoj3675: [Apio2014]序列分割(斜率优化dp)

    传送门 斜率优化dp经典题目. 首先需要证明只要选择的K个断点是相同的,那么得到的答案也是相同的. 根据分治的思想,我们只需要证明有两个断点时成立,就能推出K个断点时成立. 我们设两个断点分成的三段连 ...

  5. BZOJ3675 Apio2014 序列分割 【斜率优化】

    Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序列,小H需要重复k次以下的步骤: 1.小H首 ...

  6. BZOJ 3675: [Apio2014]序列分割 动态规划 + 斜率优化 + 卡精度

    Code: #include<bits/stdc++.h> #define N 100006 #define M 205 #define ll long long #define setI ...

  7. 【BZOJ3675】序列分割(斜率优化,动态规划)

    [BZOJ3675]序列分割(斜率优化,动态规划) 题面 Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得 ...

  8. BZOJ_3675_[Apio2014]序列分割_斜率优化

    BZOJ_3675_[Apio2014]序列分割_斜率优化 Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了 ...

  9. 【BZOJ-3675】序列分割 DP + 斜率优化

    3675: [Apio2014]序列分割 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 1420  Solved: 583[Submit][Statu ...

  10. BZOJ 3675: [Apio2014]序列分割( dp + 斜率优化 )

    WA了一版... 切点确定的话, 顺序是不会影响结果的..所以可以dp dp(i, k) = max(dp(j, k-1) + (sumn - sumi) * (sumi - sumj)) 然后斜率优 ...

随机推荐

  1. p211有界自共轭算子T是实数集合的子集

    对条件 取非   是 ∉谱集合的实数 才对  现在是  入  属于正则点集 他  然后  又说T 的谱是实数 这不矛盾吗 这里根据   必要性    推出 蓝色和红色矛盾    矛盾就是 这是谱点 然 ...

  2. [转帖]SAP一句话入门:Project System

    SAP一句话入门:Project System http://blog.vsharing.com/MilesForce/A621279.html 这是SAP ERP入门的最后一篇了. 我们这些死跑龙套 ...

  3. K3CLOUD数据权限授权

    1.定义角色,把用户放入角色内 2.设置数据规则 3.设置业务对象功能授权

  4. DTW动态时间规整

    参考: https://blog.csdn.net/raym0ndkwan/article/details/45614813

  5. Django 2.11 静态页面404 解决

    在settings中配置 STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR,"static"), ...

  6. jenkins和jdk版本问题

    问题:公司业务是用的jdk1.7的,但最新版的jenkins (jenkins-2.138.2-1.1.noarch.rpm)却只支持jdk1.8 分析: 1.公司业务用的jdk1.7不能换,不然影响 ...

  7. php1

    正则表达式 $p = '/name:(\w+\s?\w+)/'; $str = "name:steven jobs"; preg_match($p, $str, $match); ...

  8. Hibernate 连接不同数据库的方言

    RDBMS 方言 DB2 org.hibernate.dialect.DB2Dialect DB2 AS/400 org.hibernate.dialect.DB2400Dialect DB2 OS3 ...

  9. HTTP协议 - 使用php模拟get/post请求

    首先 有个疑问, 是不是只有浏览器才能发送http 请求? 答案肯定是错的,第一篇就说了,http是由请求行,请求头,请求主体三个部分组成,那么我们可不可以用代码来模拟一下get和post请求呢: 首 ...

  10. 洛谷 P2151 [SDOI2009]HH去散步

    题目链接 思路 如果没有不能走上一条边的限制,很显然就是dp. 设f[i][j]表示到达i点走了j步的方案数,移到k点可以表示为f[k][j+1]+=f[i][j]. 如果有限制的话,可以考虑用边表示 ...