题意:

已知一个序列 { a [ i ] } ,求取出从中若干不大于 KK 的区间,求这些区间和的最大值。

细节:

没有细节???感觉没有???

分析:

听说有两种方法!!!

好吧实际上是等价的只是看似状态不同罢了~~~ QAQ

Round1:枚举当前点取或不取,当前点 i 取的话那么在前 KK 的数中必须要选择一个数字点 k 不取并且将 k+1i 做为新的区间,最后取最优的 k 作为转移记录下来,并且其满足最有子结构。

所以状态就是:dp[i][0/1] 表示以 i 为结尾是否取 i 最大的区间

自然转移就是:

dp [ i ][ 0 ] = max ( dp [ i-1 ][ 0 ] , dp [ i-1 ][ 1 ] )

dp [ i ][ 1 ] = max ( dp [ i ][ 1 ] , dp [ k ][ 0 ] + sum [ i ] - sum [ k ]) ( i-KK ≤ k ≤ i - 1 )

Round2:好吧还有一种思路直接考虑那个断点 k ,并且不去这个断点。

状态就变成了: f [ i ] 表示以 i 为结尾且必须取 i 的最大价值。

根据思路转移个人感觉玄学:

f [ i ] = max ( f [ i ] , f [ k -1 ] + sum [ i ] - sum [ k ] ) ( i-KK ≤ k ≤ i - 1 )

其中的 sum [ ] 都表示序列的前缀和,同上。

好吧事实总不尽人意,看一眼数据范围顿时吸一口氧气,但是无论怎样都是 T L E ,好像是废话,活活的 N × N 的算法啊。但是观察观察方程, 比如 Round 2 中的我们使用一种高级的数学方法——加法交换律!!!

就能把式子变成这个样子 —— f [ i ] = max ( f [ k -1 ] - sum [ k ] ) + sum [ i ]

这是时候你就应该大叫一声这是定区间求最值啊,然后你想怎么做都可以了吧,线段树权值、树状数组之类的 好吧我们还是正常一点还是不去惹 log n 的时间复杂万一卡常呢,最后你就会明智的选择单调队列啦啦啦啦~~~(Ps:单调递减,咳咳)

其实某些大佬闭着眼睛不用想都可以,比如 c l yy j ql c t,啦啦啦

代码的荣耀时刻:

Round1:

#include<bits/stdc++.h>
#define LL long long
#define MAXN 100010
using namespace std; LL f[MAXN], dp[MAXN][2];
int que[MAXN], n, m; int main(){
scanf("%d%d", &n, &m);
for (int i=1; i<=n; i++){
LL x;
scanf("%lld", &x);
f[i]=f[i-1]+x;
}
int tail=1, head=1;
que[1]=0;
for (int i=1; i<=n; i++) {
dp[i][0]=max(dp[i-1][1], dp[i-1][0]);
while (head<=tail && que[head]<max(0, i-m)) head++;
dp[i][1]=dp[que[head]][0]-f[que[head]]+f[i];
while (head<=tail && dp[que[tail]][0]-f[que[tail]]<=dp[i][0]-f[i]) tail--;
que[++tail]=i;
}
printf("%lld\n", max(dp[n][1], dp[n][0]));
return 0;
}
Round2:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int MAXN=100010; int n, k, que[MAXN];
LL f[MAXN], dp[MAXN]; int main(){
scanf("%d%d", &n, &k);
for (int i=1; i<=n; i++) {
LL x;
scanf("%lld", &x);
f[i]=f[i-1]+x;
}
int head=1, tail=1;
for (int i=1; i<=n; i++){
while (head<=tail && que[head]<max(i-k, 0)) ++head;
dp[i]=dp[max(que[head]-1, 0)]+f[i]-f[que[head]];
while (head<=tail && dp[max(que[tail]-1, 0)]-f[que[tail]]<=dp[i-1]-f[i]) --tail;
que[++tail]=i;
}
printf("%lld\n", dp[n]);
return 0;
}

小结:

其实小蒟蒻觉得像这种类似单调队列优化 1 D / 1 D 动态规划的情况,难在最初始状态思考以及转移,优化过程以及代码实现可以多练体进行熟练。

Luogu 2627 修建草坪 (动态规划Dp + 单调队列优化)的更多相关文章

  1. [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)

    DP + 单调队列优化 + 平衡树 好题 Description Given an integer sequence { an } of length N, you are to cut the se ...

  2. [luogu P1776] 宝物筛选 解题报告(单调队列优化DP)

    题目链接: https://www.luogu.org/problemnew/show/P1776 题目: 终于,破解了千年的难题.小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF ...

  3. 1023: [SHOI2008]cactus仙人掌图(DP+单调队列优化)

    这道题吗= =首先解决了我多年以来对仙人掌图的疑问,原来这种高大上的东西原来是这个啊= = 然后,看到这种题,首先必须的就是缩点= = 缩点完之后呢,变成在树上找最长路了= =直接树形dp了 那么那些 ...

  4. Codeforces 1077F2 Pictures with Kittens (hard version)(DP+单调队列优化)

    题目链接:Pictures with Kittens (hard version) 题意:给定n长度的数字序列ai,求从中选出x个满足任意k长度区间都至少有一个被选到的最大和. 题解:数据量5000, ...

  5. P3084 [USACO13OPEN]照片Photo (dp+单调队列优化)

    题目链接:传送门 题目: 题目描述 Farmer John has decided to assemble a panoramic photo of a lineup of his N cows ( ...

  6. Codeforces 445A Boredom(DP+单调队列优化)

    题目链接:http://codeforces.com/problemset/problem/455/A 题目大意:有n个数,每次可以选择删除一个值为x的数,然后值为x-1,x+1的数也都会被删除,你可 ...

  7. bzoj 1855 dp + 单调队列优化

    思路:很容易写出dp方程,很容易看出能用单调队列优化.. #include<bits/stdc++.h> #define LL long long #define fi first #de ...

  8. 股票交易(DP+单调队列优化)

    题目描述 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi, ...

  9. 【简洁易懂】CF372C Watching Fireworks is Fun dp + 单调队列优化 dp优化 ACM codeforces

    题目大意 一条街道有$n$个区域. 从左到右编号为$1$到$n$. 相邻区域之间的距离为$1$. 在节日期间,有$m$次烟花要燃放. 第$i$次烟花燃放区域为$a_i$ ,幸福属性为$b_i$,时间为 ...

随机推荐

  1. HDU-1003:Max Sum(优化)

    Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  2. Azure service bus Topic基本用法

    我们在升级一个POS系统的时候,决定使用微软公有云计算平台下的Azure ServiceBus 进行POS客户端与服务器的交互. 本文主要时作者在学习使用 Azure SDK for .NET 操作由 ...

  3. C语言的面向对象技术

    引言:面向过程的C有效率高,代码紧凑的特点,在单片机嵌入式领域是C的主要阵地,while(1)+中断是其主要的开发模式,但是当系统复杂到一定程度,想要添加一个功能需要改动很多地方,耦合性太强:跟别人交 ...

  4. C. Functions again DP + 分类讨论

    http://codeforces.com/contest/789/problem/C 首先按题目要求处理出dis数组. 那么对于任意一个区间,[L, R],是dis[L] - dis[L + 1] ...

  5. 安卓新的联网方式 Volley的使用(2)

    如果使用volley 获取 网络图片 最好还是用 Volley 提供的NetworkImageView类,  可以很轻松的 完成工作, 而且他可以设置缓存, lru 和 sd卡的缓存.一些都封装好了. ...

  6. C/C++程序员应聘常见面试题深入剖析(1)

    摘自:http://blog.csdn.net/zhoudengqing 1.引言 本文的写作目的并不在于提供C/C++程序员求职面试指导,而旨在从技术上分析面试题的内涵.文中的大多数面试题来自各大论 ...

  7. 原来MFC窗口样式随字符集而改变

    以前好像发现,MFC窗口上按钮的自动样式有时是有亮色边框3D效果的,有时没有,不知道原因,也没有追究,今天正好有机会发现了原因,原来是随字符集而改变的. 1.Unicode版本下的窗口 2.未设置的窗 ...

  8. 如何在Kubernetes里创建一个Nginx service

    Jerry之前的文章如何在Kubernetes里创建一个Nginx应用,已经使用kubectl命令行创建了Pod,但是在kubernetes中,Pod的IP地址会随着Pod的重启而变化,因此用Pod的 ...

  9. Python学习日志9月14日

    今天早晨又没有专心致志的学习,我感觉我可能是累了,需要减轻学习的程度来调整一下咯.这几天装电脑弄的昏天暗地的,身体有点吃不消了.时间真是神奇的魔法,这半个月来,每隔几天都有想要改变策略的想法.今天早晨 ...

  10. DRBD+NFS+Keepalived高可用环境

    1.前提条件 准备两台配置相同的服务器 2.安装DRBD [root@server139 ~]# yum -y update kernel kernel-devel [root@server139 ~ ...