征途这是一道十分经典的斜率优化

我们可以从题目中的方差来想,也就很容易的到这个式子

\[ans=m^2*\frac{\sum_{i=1}^{m}{(x_i-{\overline{x}})^2}}{m}
\]

化简就会得到

\[ans=m*\sum_{i=1}^{m}{(x_i-{\overline{x}})^2}
\]

在化简得

\[ans={m*\sum_{i=1}^{m}{x_i}^2}+{\sum_{i=1}^{m}{x_i}}
\]

经过观察,我们可以很容易发现\(\sum_{i=1}^{m}{x_i}\)是定值,同时\(m*\sum_{i=1}^{m}{x_i}^2\)中的\(m\)也是定值,所以我们的目标就是让\(\sum_{i=1}^{m}{{x_i}^2}\)最小

我们令\(dp[i][j]=\min\{dp[i-1][j-k]+(sum[j]-sum[j-k])^2\}\)

其中我们令\(sum[i]=\sum_{k=1}^{i}{val_k}\)

其中\(val_k\)是第k段路的长度

由此我们就可得到一个开o2可以卡成80的代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cctype>
  5. using namespace std;
  6. long long n,m,dp[3001][3001],sum[3001];
  7. const int BufferSize=100*1000;
  8. char buffer[BufferSize],*head,*tail;
  9. bool not_EOF=true;
  10. inline char Getchar(){
  11. if(not_EOF and head==tail){
  12. int len=fread(buffer,1,BufferSize,stdin);
  13. not_EOF=len!=0;
  14. head=buffer,tail=head+len;
  15. }
  16. return not_EOF?*head++:-1;
  17. }
  18. inline long long rd(){
  19. long long x=0,s=1;
  20. char c=Getchar();
  21. for(;!isdigit(c) and not_EOF;c=Getchar()) if(c=='-') s=-1;
  22. for(; isdigit(c) and not_EOF;c=Getchar()) x=(x<<1)+(x<<3)+(c^48);
  23. return s*x;
  24. }
  25. inline void scan(char *str){
  26. char c=Getchar();
  27. for(; isspace(c) and not_EOF;c=Getchar());
  28. for(;!isspace(c) and not_EOF;c=Getchar()) *(str++)=c;
  29. *str=0;
  30. }
  31. int main(){
  32. memset(dp,0x7f,sizeof(dp));
  33. n=rd(),m=rd();
  34. for(int i=1;i<=n;i++){
  35. long long x=rd();
  36. sum[i]=sum[i-1]+x;
  37. }
  38. dp[0][0]=-sum[n]*sum[n];
  39. for(int i=0;i<m;i++){
  40. for(int j=0;j<=n;j++){
  41. for(int k=0;k<=n-j;k++){
  42. dp[i+1][j+k]=min(dp[i+1][j+k],dp[i][j]+(sum[j+k]-sum[j])*(sum[j+k]-sum[j])*m);
  43. }
  44. }
  45. }
  46. printf("%lld",dp[m][n]);
  47. return 0;
  48. }

但是我们可以发现这个代码是\(O(nm)\)的,显然我是不可以接受的。其实我们可以很容易证明这个的决策单调性,于是我们就可以用斜率优化

我们令\(y<x<i\)

因为决策单调性,所以对于决策\(i\)时,k转移必定比j转移要优,我们就可以得到这么一个式子

\[dp[i-1][x]+(sum[j]-sum[x])^2<dp[i-1][y]+(sum[j]-sum[y])^2
\]

化简得

\[\frac{(dp[i-1][x]+sum[x]^2)-(dp[i-1][y]+sum[y]^2)}{sum[x]-sum[y]}<2*sum[j]
\]

这样我们就可以用斜率又花了

我们把\(p_1(dp[i-1][x]+sum[x]^2,sum[x])\)和\(p_2(dp[i-1][y]+sum[y]^2,sum[y])\)看做\(p_1,p_2\)两个点,刚刚那个式子也就是它们所连线的斜率表达式

我们也就可以得到这样的代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. long long n,m,dp[3001][3001],sum[3001];
  6. int q[3001];
  7. double getpoint(int i,int p){return (double)dp[i][p]+sum[i]*sum[i];}
  8. double slope(int j,int k,int p){return (double)(getpoint(j,p)-getpoint(k,p))/(double)(sum[j]-sum[k]);}
  9. int main(){
  10. scanf("%lld%lld",&n,&m);
  11. for(int i=1;i<=n;i++){
  12. long long x;
  13. scanf("%lld",&x);
  14. sum[i]=sum[i-1]+x;
  15. dp[i][1]=sum[i]*sum[i];
  16. }
  17. for(int k=2;k<=m;k++){
  18. int head=1,tail=0;
  19. for(int i=1;i<=n;i++){
  20. while(head<tail and slope(q[head],q[head+1],k-1)<2*sum[i])head++;
  21. int j=q[head];
  22. dp[i][k]=dp[j][k-1]+(sum[j]-sum[i])*(sum[j]-sum[i]);
  23. while(head<tail and slope(q[tail],q[tail-1],k-1)>slope(q[tail],i,k-1))tail--;
  24. q[++tail]=i;
  25. }
  26. }
  27. printf("%lld",m*dp[n][m]-sum[n]*sum[n]);
  28. return 0;
  29. }

bzoj4518征途 斜率优化的更多相关文章

  1. [SDOI2015][bzoj4518] 征途 [斜率优化dp]

    题面 传送门 思路 把$vm^2$展开化一下式子,可以得到这样的等价公式: $vm^2=m\sum_{i=1}^m a_i^2-\sum_{i=1}^m a_i$ 那么我们要最小化的就是$\sum_{ ...

  2. P4072 [SDOI2016](BZOJ4518) 征途 [斜率优化DP]

    题目描述 Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜.所以,一段路 ...

  3. 洛谷 P4072 [SDOI2016]征途 斜率优化DP

    洛谷 P4072 [SDOI2016]征途 斜率优化DP 题目描述 \(Pine\) 开始了从 \(S\) 地到 \(T\) 地的征途. 从\(S\)地到\(T\)地的路可以划分成 \(n\) 段,相 ...

  4. 【BZOJ4518】[Sdoi2016]征途 斜率优化

    [BZOJ4518][Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除 ...

  5. bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

    题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...

  6. bzoj4518[Sdoi2016]征途 斜率优化dp

    4518: [Sdoi2016]征途 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1657  Solved: 915[Submit][Status] ...

  7. 【bzoj4518】[Sdoi2016]征途 斜率优化dp

    原文地址:http://www.cnblogs.com/GXZlegend/p/6812435.html 题目描述 Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界 ...

  8. [bzoj4518][Sdoi2016]征途-斜率优化

    Brief Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须 ...

  9. BZOJ 4518: [Sdoi2016]征途 [斜率优化DP]

    4518: [Sdoi2016]征途 题意:\(n\le 3000\)个数分成m组,一组的和为一个数,求最小方差\(*m^2\) DP方程随便写\(f[i][j]=min\{f[k][j-1]+(s[ ...

随机推荐

  1. Wannafly挑战赛29A御坂美琴

    传送门 这套题很有意思2333 蠢了--首先先判总共加起来等不等于\(n\),不是的话就不行 然后dfs记录\(n\)不断分下去能分成哪些数,用map记录一下,判断是否所有数都能被分出来就是了 //m ...

  2. 模拟 URAL 1149 Sinus Dances

    题目传送门 /* 模拟:找到规律分别输出就可以了,简单但是蛮有意思的 */ #include <cstdio> #include <algorithm> #include &l ...

  3. 386 Lexicographical Numbers 字典序排数

    给定一个整数 n, 返回从 1 到 n 的字典顺序.例如,给定 n =1 3,返回 [1,10,11,12,13,2,3,4,5,6,7,8,9] .请尽可能的优化算法的时间复杂度和空间复杂度. 输入 ...

  4. kafka的server.properties配置文件参考示范(图文详解)(多种方式)

    简单点的,就是 kafka_2.11-0.8.2.2.tgz的3节点集群的下载.安装和配置(图文详解) 但是呢,大家在实际工作中,会一定要去牵扯到调参数和调优问题的.以下,是我给大家分享的kafka的 ...

  5. C# 输出控制台结果到文件

    StreamWriter sw = new StreamWriter(@"c:\output.txt"); Console.SetOut(sw); Console.WriteLin ...

  6. Oracle数据库数据显示乱码问题解决方法。

    一.问题描述:       在将其它数据库的数据导出文件导入本地新建数据库时,所导入的数据全部是乱码,一般表现为数据表中列的值类似于"?????",即内容大部分为?的表现形式.初步 ...

  7. js中取整数的方法

    1.取整的方法 Math.floor( ) Math 对象的方法--取比当前数值小的最大整数(下取整). Math.ceil( ) Math对象的方法--取比当前数值大的最小整数(上取整). Math ...

  8. iframe子页面让父页面跳转 parent.location.href

    if ($roleNum < 9) { echo "<script > parent.location.href='admin_login.php' </script ...

  9. (转)版本管理工具介绍——SVN篇(二)

    http://blog.csdn.net/yerenyuan_pku/article/details/72620498 上一篇文章我介绍了一下SVN,以及SVN服务器的安装,相信大家都安装了,接下来我 ...

  10. JMeter怎样测试WebSocket,示例演示(二)

    一.测试案例演示 以  http://www.websocket.org/echo.html 网站为例. 地址为:ws://echo.websocket.org 二.长连接的影响 1.没有勾选stre ...