题意

有一个长度为 \(n\) 的序列 \(A\) 和常数 \(L, P\) ,你需要将它分成若干段,每 \(P\) 一段的代价为 \(| \sum ( A_i ) − L|^P\) ,求最小代价的划分方案。

\(n \le 10^5 , 1 \le P \le 10\)

题解

考虑暴力 \(O(n^2)\) dp。

\[dp_i = \min_{j = 0} ^ {i - 1} |sum_j - sum_i - L|^P + dp_j
\]

这个方程是具有决策单调性的。

决策单调性是指,对于任意 \(u < v < i < j\) ,若在 \(i\) 处决策 \(v\) 优于决策 \(u\) ,则在 \(j\) 处必有决策 \(v\) 优于决策 \(u\) 。

至于证明,你考虑那是个二次函数,一阶导数单增等性质就可以了。

然后考虑用一个栈来维护每个决策会更新的区间就行了,新加入一个决策时要二分得到它的区间。

令 \(f(i, j)\) 为从 \(i\) 转移到 \(j\) 得到的 \(dp_j\) 。

具体二分的时候就找到 \(f(i, mid) - f(stk[top], mid)\) 的零点就行了,之后的点肯定 \(i\) 更优。

然后每次转移的话就二分找到当前这个点属于的决策区间,注意边界问题,然后每次要把栈顶所有当前不优于它的状态都要弹掉。

所以最后复杂度就是 \(O(n \log n)\) 的。

总结

决策单调性优化都可以用栈维护转移区间,然后每次二分找转移点,以及求区间就行了。

代码

  1. #include <bits/stdc++.h>
  2. #define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
  3. #define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
  4. #define Set(a, v) memset(a, v, sizeof(a))
  5. #define Cpy(a, b) memcpy(a, b, sizeof(a))
  6. #define debug(x) cout << #x << ": " << (x) << endl
  7. #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
  8. using namespace std;
  9. typedef long double ld;
  10. typedef long long ll;
  11. template<typename T> inline bool chkmin(T &a, T b) {return b < a ? a = b, 1 : 0;}
  12. template<typename T> inline bool chkmax(T &a, T b) {return b > a ? a = b, 1 : 0;}
  13. inline int read() {
  14. int x(0), sgn(1); char ch(getchar());
  15. for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
  16. for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
  17. return x * sgn;
  18. }
  19. void File() {
  20. #ifdef zjp_shadow
  21. freopen ("P1912.in", "r", stdin);
  22. freopen ("P1912.out", "w", stdout);
  23. #endif
  24. }
  25. const int N = 1e5 + 1e3;
  26. int n, Pow, L;
  27. int sum[N], pre[N], stk[N], seg[N];
  28. int ans[N]; char str[N][50];
  29. ld dp[N];
  30. ld fpm(ld x, int power) {
  31. ld res = 1;
  32. for (; power; power >>= 1, x *= x)
  33. if (power & 1) res *= x;
  34. return res;
  35. }
  36. ld Calc(int S, int T) {
  37. return S >= T ? 1e18 + 1 : dp[S] + fpm(abs(sum[T] - sum[S] - L), Pow);
  38. }
  39. int main () {
  40. File();
  41. int cases = read();
  42. while (cases --) {
  43. n = read(); L = read(); Pow = read();
  44. For (i, 1, n) {
  45. scanf ("%s", str[i]);
  46. sum[i] = sum[i - 1] + strlen(str[i]) + 1;
  47. }
  48. ++ L;
  49. int top = 1; stk[1] = seg[1] = dp[0] = 0;
  50. For (i, 1, n) {
  51. int pos = upper_bound(seg + 1, seg + top + 1, i) - seg - 1;
  52. dp[i] = Calc(pre[i] = stk[pos], i);
  53. for (; top && Calc(stk[top], seg[top]) > Calc(i, seg[top]); -- top);
  54. int l = seg[top], r = n, res = 0;
  55. while (l <= r) {
  56. int mid = (l + r) >> 1;
  57. if (Calc(stk[top], mid) <= Calc(i, mid))
  58. res = mid, l = mid + 1;
  59. else
  60. r = mid - 1;
  61. }
  62. if (res < n)
  63. seg[++ top] = res + 1, stk[top] = i;
  64. }
  65. if (dp[n] > 1e18) puts("Too hard to arrange");
  66. else {
  67. printf ("%lld\n", (ll) dp[n]);
  68. top = 0;
  69. for (int u = n; u; u = pre[u])
  70. ans[++ top] = u;
  71. ans[top + 1] = 0;
  72. Fordown (i, top, 1) For(j, ans[i + 1] + 1, ans[i])
  73. printf ("%s%c", str[j], j == jend ? '\n' : ' ');
  74. }
  75. puts("--------------------");
  76. }
  77. return 0;
  78. }

[NOI2009]诗人小G(dp + 决策单调性优化)的更多相关文章

  1. [NOI2009]诗人小G --- DP + 决策单调性

    [NOI2009]诗人小G 题目描述: 小G是一个出色的诗人,经常作诗自娱自乐. 但是,他一直被一件事情所困扰,那就是诗的排版问题. 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并 ...

  2. 2018.09.28 bzoj1563: [NOI2009]诗人小G(决策单调性优化dp)

    传送门 决策单调性优化dp板子题. 感觉队列的写法比栈好写. 所谓决策单调性优化就是每次状态转移的决策都是在向前单调递增的. 所以我们用一个记录三元组(l,r,id)(l,r,id)(l,r,id)的 ...

  3. [bzoj1563][NOI2009]诗人小G(决策单调性优化)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1563 分析: 首先可得朴素的方程:f[i]=min{f[j]+|s[j]-j-s[i] ...

  4. BZOJ1563 NOI2009 诗人小G【决策单调性优化DP】

    LINK 因为是图片题就懒得挂了 简要题意:有n个串,拼接两个串需要加一个空格,给你l和p,问你拼接后每个串的总长减l的绝对值的p次方的最小值 首先打表发现一下这题是决策单调的对于所有数据都成立就当他 ...

  5. 洛谷P1912 [NOI2009]诗人小G(决策单调性)

    传送门 题解 决策单调性是个啥……导函数是个啥……这题解讲的是啥……我是个啥…… //minamoto #include<iostream> #include<cstdio> ...

  6. 【BZOJ1563】诗人小G(决策单调性DP)

    题意:给定N,L,P,求f[N] sum[i]递增,L<=3e6,P<=10 思路:四边形不等式的证明见https://www.byvoid.com/zhs/blog/noi-2009-p ...

  7. P1912 [NOI2009]诗人小G[决策单调性优化]

    地址 n个数划分若干段,给定$L$,$p$,每段代价为$|sum_i-sum_j-1-L|^p$,求总代价最小. 正常的dp决策单调性优化题目.不知道为什么luogu给了个黑题难度.$f[i]$表示最 ...

  8. bzoj1563: [NOI2009]诗人小G 决策单调性(1D1D)

    目录 题目链接 题解 代码 题目链接 bzoj1563: [NOI2009]诗人小G 题解 \(n^2\) 的dp长这样 \(f_i = min(f_j + (sum_i - sum_j - 1 - ...

  9. P1912 [NOI2009]诗人小G

    P1912 [NOI2009]诗人小G 思路: 平行四边形不等式优化dp 因为f(j, i) = abs(sum[i]-sum[j]+i-j-1-l)^p 满足平行四边形不等式 j < i f( ...

  10. 1563: [NOI2009]诗人小G

    1563: [NOI2009]诗人小G https://lydsy.com/JudgeOnline/problem.php?id=1563 分析: 直接转移f[i]=f[j]+cost(i,j),co ...

随机推荐

  1. 工作流引擎JFlow与activiti 对比分析(一)5种基本控制流模式的对比

    为了更好的说明activiti 与jflow的两款工作流引擎的特点与区别,我们按照如下几个方面做一次全面的.客观的对比. 首先activiti是国外的一款开源的工作流程引擎,在国际上影响比较深远与广泛 ...

  2. weblogic 安装配置打补丁

    Master Note on WebLogic Server (WLS) Patches, Upgrade Installers, and Full Installers

  3. zabbix3.4 端口和进程监控配置

    虚拟机系统版本:centos7.5 zabbix server 版本:zabbix3.4 配置步骤:待定 近期即将更新!

  4. iPad----------教你如何查询ipad型号

    1.首先进入苹果官网 找到support    https://support.apple.com 2.找到查询ipad型号的地方  点击Check  coverage for your produc ...

  5. Paint.FontMetrics

    要了解TextView对文本的绘制,那么就需要了解Paint.FontMetircs. 官方对该类的解释是:Class that describes the various metrics for a ...

  6. Activity的启动流程

    前言:新启动一个activity分为两种情况,第一种是在Launcher的桌面点击icon图标启动一个新的应用,第二种是在应用启动的情况下从OneActivity->TwoActivity 其实 ...

  7. 实战项目中Java heap space错误的解决

    部标GPS通讯系统在上线之后,经过不断调试,终于稳定运行一段时间,后来又遇到了Java heap space错误异常!日志如下: 说明系统中有未释放的对象.如何找出这些未释放对象以及监控JVM堆内存, ...

  8. 在Visual Studio 2017上配置Glut

    在Visual Studio 2017上配置Glut 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 在Visual Studio 2017上配置并使用 ...

  9. 通过shell命令往android中写入配置

    C:\Users>adb shell setprop "persist.sys.btylevel" 100 C:\Users>adb shell getprop &qu ...

  10. echarts堆叠图添加总量

    echarts在使用中往往会遇到需要展示总量信息的情况,比较典型的就是3维统计的堆叠柱状图 堆叠是在柱状图的基础上,给几项设置同一stack来实现的.不考虑在tips中实现总和,有两种方式可以实现总和 ...