正题

题目链接:https://www.luogu.com.cn/problem/P1912


题目大意

给出\(n\)个字符串,把这些字符串依次用空格(算一个长度)连接分成若干段,若一段长度为\(x\),那么代价是\(|x-L|^P\)

求代价和最小的方案,如果代价大于\(1e18\)则输出其他东西

\(1\leq n\leq 10^5,1\leq L\leq 3\times 10^6,1\leq P\leq 10\)


解题思路

\(s_i\)表示前\(i\)个字符串的长度和加\(i\),那么有转移方程

\[f_i=min\{f_j+|s_i-s_j-1-L|^P\}
\]

这个转移很麻烦不能直接用单调队列之类的优化,但是它满足四边形不等式

\(w_{i,j}=|s_i-s_j-1-L|^P\),然后满足

\[w_{i,j}+w_{i+1,j+1}\leq w_{i,j+1}+w_{i+1,j}
\]

这里就不证明了,因为证明需要用到求导。

感谢理解的话可以发现因为有个\(abs\),所以对于一个决策来说是先下后上,而且两个决策最多只有一个交点。

所以有决策单调性,我们用单调队列维护一个该决策和它的下一个决策的交换点\(k_i\),然后每次判断新加入的点与队尾的前一个的交换点是否会代替掉队尾即可。

求交换点的话用二分就好了。

时间复杂度\(O(Tn\log n)\)

怕转移太大可以用\(long\ double\)存,因为如果很大的时候精度就不需要管了,我们只需要知道它是否超过\(1e18\)就好了。


code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cmath>
  5. #define ll long double
  6. using namespace std;
  7. const int N=1e5+10;
  8. int T,n,L,P,p[N],k[N],q[N];
  9. ll f[N],s[N];
  10. char st[N][31];
  11. ll power(ll x,int b){
  12. ll ans=1;
  13. while(b){
  14. if(b&1)ans=ans*x;
  15. x=x*x;b>>=1;
  16. }
  17. return ans;
  18. }
  19. ll calc(int j,int i)
  20. {return f[j]+power(fabs(s[i]-s[j]-1-L),P);}
  21. int bound(int i,int j){
  22. int l=i,r=n;
  23. while(l<=r){
  24. int mid=(l+r)>>1;
  25. if(calc(i,mid)<calc(j,mid))l=mid+1;
  26. else r=mid-1;
  27. }
  28. return l;
  29. }
  30. void print(int n){
  31. if(!n)return;print(p[n]);
  32. for(int i=p[n]+1;i<n;i++)
  33. printf("%s ",st[i]);
  34. puts(st[n]);
  35. }
  36. int main()
  37. {
  38. scanf("%d",&T);
  39. while(T--){
  40. scanf("%d%d%d",&n,&L,&P);
  41. for(int i=1;i<=n;i++){
  42. scanf("%s",st[i]);
  43. s[i]=s[i-1]+strlen(st[i])+1;
  44. }
  45. int head=1,tail=1;q[1]=0;
  46. for(int i=1;i<=n;i++){
  47. while(head<tail&&k[head]<=i)head++;
  48. f[i]=calc(q[head],i);p[i]=q[head];
  49. while(head<tail&&k[tail-1]>=bound(q[tail],i))tail--;
  50. k[tail]=bound(q[tail],i);q[++tail]=i;
  51. }
  52. if(f[n]>1e18)puts("Too hard to arrange");
  53. else printf("%lld\n",(long long)f[n]),print(n);
  54. puts("--------------------");
  55. }
  56. return 0;
  57. }

P1912-[NOI2009]诗人小G【四边形不等式,单调队列】的更多相关文章

  1. P1912 [NOI2009]诗人小G

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

  2. 不失一般性和快捷性地判定决策单调(洛谷P1912 [NOI2009]诗人小G)(动态规划,决策单调性,单调队列)

    洛谷题目传送门 闲话 看完洛谷larryzhong巨佬的题解,蒟蒻一脸懵逼 如果哪年NOI(放心我这样的蒟蒻是去不了的)又来个决策单调性优化DP,那蒟蒻是不是会看都看不出来直接爆\(0\)?! 还是要 ...

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

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

  4. [NOI2009]诗人小G 四边形优化DP

    题目传送门 f[i] = min(f[j] + val(i,j); 其中val(i,j) 满足 四边形dp策略. 代码: #include<bits/stdc++.h> using nam ...

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

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

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

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

  7. 1563: [NOI2009]诗人小G

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

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

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

  9. LG1912 [NOI2009]诗人小G

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

  10. [NOI2009] 诗人小G [题解]

    诗人小G 题目大意 给出 \(n\) 个长度不超过 \(30\) 的句子,要求你对其进行排版. 对于每一行,有一个规定的行标准长度 \(L\) ,每一行的不协调度等于该行的实际长度与行标准长度差的绝对 ...

随机推荐

  1. malloc 和new , free 和delete的区别

    #include <iostream>using namespace std;class user{ public: int age; int number; void test() { ...

  2. Object 类中的主要结构

    == 操作符与equals 方法 == 操作符  equals 方法  重写equals() 方法的 toString()  方法

  3. c++本地动态连接库代码

    c++本地动态连接库代码 1 #pragma once 2 #include "stdafx.h" 3 4 #ifdef PERSON_EXPORTS 5 #define PERS ...

  4. C#中Finalize方法的问题

    ninputer在关于"值类型的Finalize不会被调用"中(http://blog.joycode.com/lijianzhong/archive/2005/01/13/429 ...

  5. ubuntu黑屏无法进入系统【Recovery Mode急救】

    一.问题 前言:因为一次美化配置ubuntu导致系统启动黑屏,无法进入系统.之前并没有系统备份,后果严重还好修复了,记录下修复步骤备用.  事件:就是因为修改了 /usr/share/gnome-sh ...

  6. 2020年秋游戏开发-flappy bird

    此作业要求参考https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11577 GitHub地址为https://github.com/15011 ...

  7. 解析ThreadPoolExecutor类是如何保证线程池正确运行的

    摘要:对于线程池的核心类ThreadPoolExecutor来说,有哪些重要的属性和内部类为线程池的正确运行提供重要的保障呢? 本文分享自华为云社区<[高并发]通过源码深度解析ThreadPoo ...

  8. Mysql 日期格式化 复杂日期区间查询

    前言 最近在做项目涉及到Mysql的复杂日期查询,日期查询其实在数据库中查询其实还是用的挺多的,比如查询开始日期到结束日期的区间信息,查询日期小于有效日期的信息,查询当天的日期,明天的日期,做比较等. ...

  9. (七)羽夏看C语言——模板(C++)

    写在前面   由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...

  10. Python入门学习之:10分钟1500访问量

    看效果: 不扯没用的,直接上代码: # author : sunzd # date : 2019/9/01 # position : beijing from fake_useragent impor ...