1.HDU3507

裸题,有助于理解斜率优化的精髓。

dp[i]=min(dp[j]+m+(sum[i]-sum[j])2)

很显然不是单调队列。

根据斜率优化的的定义,就是先设两个决策j,k

什么时候我们认为在 i 的环境下 j 比 k 好呢?根据上面的递推式,得到下面这么一个式子

dp[j]+m+(sum[i]-sum[j])2<dp[k]+m+(sum[i]-sum[k])2

打开括号:

dp[j]+m+sum[i]2+sum[j]2-2*sum[i]*sum[j]<dp[k]+m+sum[i]2+sum[k]2-2*sum[i]*sum[k]

移项,将有 i 的项移到右侧:

dp[j]+sum[j]2-dp[k]-sum[k]2<2*sum[i]*(sum[j]-sum[k])

除下来:

(dp[j]+sum[j]2-dp[k]-sum[k]2)/[2*(sum[j]-sum[k])]<sum[i]

好了这就是斜率了^_^

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. typedef long long lnt;
  5. int Q[];
  6. lnt sum[];
  7. lnt dp[];
  8. int h,t;
  9. lnt n;
  10. lnt m;
  11. lnt X(int x)
  12. {
  13. return dp[x]+sum[x]*sum[x];
  14. }
  15. lnt tp(int i,int j)
  16. {
  17. return X(i)-X(j);
  18. }
  19. lnt btm(int i,int j)
  20. {
  21. return *sum[i]-*sum[j];
  22. }
  23. int main()
  24. {
  25. while(scanf("%lld%lld",&n,&m)!=EOF)
  26. {
  27. sum[]=;
  28. for(int i=;i<=n;i++)
  29. scanf("%lld",&sum[i]);
  30. for(int i=;i<=n;i++)
  31. sum[i]+=sum[i-];
  32. h=t=;
  33. Q[]=;
  34. dp[]=;
  35. for(int i=;i<=n;i++)
  36. {
  37. while(h<t&&(tp(Q[h+],Q[h])<=sum[i]*btm(Q[h+],Q[h])))
  38. h++;
  39. dp[i]=dp[Q[h]]+m+(sum[i]-sum[Q[h]])*(sum[i]-sum[Q[h]]);
  40. while(h<t&&(tp(Q[t],Q[t-])*btm(i,Q[t])>=tp(i,Q[t])*btm(Q[t],Q[t-])))
  41. t--;
  42. Q[++t]=i;
  43. }
  44. printf("%lld\n",dp[n]);
  45. }
  46. return ;
  47. }

2.BZOJ1010: [HNOI2008]玩具装箱toy

这道题依然斜率单调

dp方程自己推:

dp[i]=min(dp[j]+(i-j-1+sum[i]-sum[j]-L)2)

依然假设在 i 的环境下决策 j 优于 k

那么:

dp[j]+(i-j-1+sum[i]-sum[j]-L)2<dp[k]+(i-k-1+sum[i]-sum[k]-L)2

将常数项与与 i 有关的项放到一起,展开:

(sum[j]+j)2-2*(i+sum[i]-L-1)*(sum[j]+j)+dp[j]<(sum[k]+k)2-2*(i+sum[i]-L-1)*(sum[k]+k)+dp[k]

设函数 f(x)=sum[x]+x , h(x)=x+sum[x]-L-1 , g(x)=dp[x]+f(x)2

得到当:

g(j)-g(k)<2*h(i)*(f(j)-f(k)) 时,j 比 k 优秀。

f(x)单调递增,斜率单调。

时间复杂度O(n)

代码:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. typedef long long lnt;
  5. lnt sum[];
  6. lnt dp[];
  7. int Q[];
  8. int h,t;
  9. int n;
  10. lnt L;
  11. lnt f(int x)
  12. {
  13. return (sum[x]+(lnt)(x));
  14. }
  15. lnt k(int x)
  16. {
  17. return ((lnt)(x)+sum[x]-L-);
  18. }
  19. lnt g(int x)
  20. {
  21. return (dp[x]+f(x)*f(x));
  22. }
  23. lnt squ(lnt x)
  24. {
  25. return x*x;
  26. }
  27. int main()
  28. {
  29. scanf("%d%lld",&n,&L);
  30. for(int i=;i<=n;i++)
  31. {
  32. scanf("%lld",&sum[i]);
  33. sum[i]+=sum[i-];
  34. }
  35. Q[]=;
  36. dp[]=;
  37. h=t=;
  38. for(int i=;i<=n;i++)
  39. {
  40. while(h<t&&g(Q[h+])-g(Q[h])<2ll*k(i)*(f(Q[h+])-f(Q[h])))
  41. h++;
  42. dp[i]=dp[Q[h]]+squ((lnt)(i-Q[h]-)+sum[i]-sum[Q[h]]-L);
  43. while(h<t&&(((g(Q[t-])-g(Q[t]))*(f(Q[t])-f(i)))>((g(Q[t])-g(i))*(f(Q[t-])-f(Q[t])))))
  44. t--;
  45. Q[++t]=i;
  46. }
  47. printf("%lld\n",dp[n]);
  48. return ;
  49. }

3.BZOJ1911: [Apio2010]特别行动队

斜率单调。

方程自己推:

设:g(x)=a*x2+b*x+c

dp[i]=max(dp[j]+g(sum[i]-sum[j]))

设在 i 环境下决策 j 优于 k

dp[j]+g(sum[i]-sum[j])>dp[k]+g(sum[i]-sum[k])

设f(x)=dp[x]+a*sum[x]2-b*sum[x]

则当:

f(j)-f(k)>2*a*sum[i]*(sum[j]-sum[k])

设 j > k 斜率单调

时间复杂度O(n)

代码:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cstdio>
  4. typedef long long lnt;
  5. lnt sum[];
  6. lnt dp[];
  7. int Q[];
  8. int h,t;
  9. int n;
  10. lnt a,b,c;
  11. lnt f(int x)
  12. {
  13. return dp[x]+a*sum[x]*sum[x]-b*sum[x];
  14. }
  15. lnt g(lnt x)
  16. {
  17. return a*x*x+b*x+c;
  18. }
  19. int main(void)
  20. {
  21. sum[]=;
  22. h=t=;
  23. scanf("%d",&n);
  24. scanf("%lld%lld%lld",&a,&b,&c);
  25. for(int i=;i<=n;i++)
  26. {
  27. scanf("%lld",&sum[i]);
  28. sum[i]+=sum[i-];
  29. }
  30. Q[]=;
  31. dp[]=;
  32. for(int i=;i<=n;i++)
  33. {
  34. while(h<t&&(f(Q[h+])-f(Q[h]))>*a*sum[i]*(sum[Q[h+]]-sum[Q[h]]))
  35. h++;
  36. dp[i]=dp[Q[h]]+g(sum[i]-sum[Q[h]]);
  37. while(h<t&&(f(Q[t])-f(Q[t-]))*(sum[i]-sum[Q[t]])<=(f(i)-f(Q[t]))*(sum[Q[t]]-sum[Q[t-]]))
  38. t--;
  39. Q[++t]=i;
  40. }
  41. printf("%lld\n",dp[n]);
  42. return ;
  43. }

4.BZOJ4518: [Sdoi2016]征途

这次变成二维的了。

都一样,展开方程+斜率优化。

这次要对于每一天进行O(n)转移,共m天,时间复杂度O(n*m)

代码:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. typedef long long lnt;
  5. lnt dp[][];
  6. lnt sum[];
  7. int Q[];
  8. lnt n,m;
  9. lnt L;
  10. int h,t;
  11. lnt squ(lnt x)
  12. {
  13. return x*x;
  14. }
  15. lnt f(int x,int i)
  16. {
  17. return dp[x][i]+m*squ(sum[x])+2ll*L*sum[x];
  18. }
  19. int main()
  20. {
  21. scanf("%lld%lld",&n,&m);
  22. for(int i=;i<=n;i++)
  23. {
  24. scanf("%lld",&sum[i]);
  25. sum[i]+=sum[i-];
  26. }
  27. L=sum[n];
  28. for(int i=;i<=n;i++)
  29. {
  30. dp[i][]=m*squ(sum[i])-2ll*L*sum[i];
  31. }
  32. for(int d=;d<=m;d++)
  33. {
  34. t=h=;
  35. Q[]=;
  36. for(int i=;i<=n;i++)
  37. {
  38. while(h<t&&(f(Q[h+],d-)-f(Q[h],d-))<2ll*m*sum[i]*(sum[Q[h+]]-sum[Q[h]]))
  39. h++;
  40. dp[i][d]=dp[Q[h]][d-]+m*squ(sum[i]-sum[Q[h]])-2ll*L*(sum[i]-sum[Q[h]]);
  41. while(h<t&&(f(Q[t],d-)-f(Q[t-],d-))*(sum[i]-sum[Q[t]])>(f(i,d-)-f(Q[t],d-))*(sum[Q[t]]-sum[Q[t-]]))
  42. t--;
  43. Q[++t]=i;
  44. }
  45. }
  46. printf("%lld\n",dp[n][m]+squ(L));
  47. return ;
  48. }

斜率优化dp练习的更多相关文章

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

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

  2. bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

    题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L ...

  3. [BZOJ3156]防御准备(斜率优化DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3156 分析: 简单的斜率优化DP

  4. 【BZOJ-1096】仓库建设 斜率优化DP

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3719  Solved: 1633[Submit][Stat ...

  5. BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

    1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...

  6. BZOJ 3156: 防御准备 斜率优化DP

    3156: 防御准备 Description   Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Output 共一个整数,表示最小的战 ...

  7. HDU2829 Lawrence(斜率优化dp)

    学了模板题之后上网搜下斜率优化dp的题目,然后就看到这道题,知道是斜率dp之后有思路就可以自己做不出来,要是不事先知道的话那就说不定了. 题意:给你n个数,一开始n个数相邻的数之间是被东西连着的,对于 ...

  8. HDU3507 Print Article(斜率优化dp)

    前几天做多校,知道了这世界上存在dp的优化这样的说法,了解了四边形优化dp,所以今天顺带做一道典型的斜率优化,在百度打斜率优化dp,首先弹出来的就是下面这个网址:http://www.cnblogs. ...

  9. HDU 3507 Print Article(斜率优化DP)

    题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上 ...

  10. 斜率优化dp(POJ1180 Uva1451)

    学这个斜率优化dp却找到这个真心容易出错的题目,其中要从n倒过来到1的确实没有想到,另外斜率优化dp的算法一开始看网上各种大牛博客自以为懂了,最后才发现是错了. 不过觉得看那些博客中都是用文字来描述, ...

随机推荐

  1. css如何实现垂直居中(5种方法)

    css如何实现垂直居中(5种方法) 一.总结 一句话总结:行内只需要简单地把 line-height 设置为那个对象的 height 值就可以使文本居中了. 块的话可以尝试 margin:auto: ...

  2. FZU--2188--过河(bfs暴力条件判断)

    过河I Time Limit: 3000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status De ...

  3. zzulioj--1089--make pair(dfs+模拟)

    1809: make pair Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 60  Solved: 44 SubmitStatusWeb Board ...

  4. windows “文件大小”与“占用空间”、文件系统与文件拷贝

    0. 文件大小与占用空间 "文件大小"和"占用空间"的差别 首先需要明确的是,"文件大小"代表着文件的真实大小(文件内容实际包含的全部字节数 ...

  5. iOS菜鸟成长笔记(1)——第一个iOS应用

    前言:阳光小强最近抽时间学习iOS开发,在学习过程中发现了很多有趣的东西也遇到了很多问题,为了在学习过程中能和大家交流,记录下学习的心得和学习成果,所以就有了这一个系列文章,希望这一系列文章能形成一个 ...

  6. Codeforces 344D Alternating Current 简单使用栈

    Description Mad scientist Mike has just finished constructing a new device to search for extraterres ...

  7. noip 2018 day2 T1 旅行 基环树 tarjan

    Code: #include<cstdio> #include<cstring> #include<string> #include<stack> #i ...

  8. javaScript for in循环遍历对象

    for循环常被我们用来遍历数组,而如何遍历对象呢? 这时就需要用到for in循环了 写一个遍历对象名简写如下: for(var xxx in ooo){console.log(xxx)} 其中xxx ...

  9. mysql 中sql 语句查询今天、昨天、近7天、近30天、一个月内、上一月数据

    ·1.几个小时内的数据 DATE_SUB(NOW(), INTERVAL 5 HOUR) 1 ·2.今天 select * from 表名 where to_days(时间字段名) = to_days ...

  10. HDU——T 1075 What Are You Talking About

    http://acm.hdu.edu.cn/showproblem.php?pid=1075 Time Limit: 10000/5000 MS (Java/Others)    Memory Lim ...