洛谷 P1714 切蛋糕 题解
P1714 切蛋糕
题目描述
今天是小Z的生日,同学们为他带来了一块蛋糕。这块蛋糕是一个长方体,被用不同色彩分成了N个相同的小块,每小块都有对应的幸运值。
小Z作为寿星,自然希望吃到的第一块蛋糕的幸运值总和最大,但小Z最多又只能吃M小块(M≤N)的蛋糕。
吃东西自然就不想思考了,于是小Z把这个任务扔给了学OI的你,请你帮他从这N小块中找出连续的k块蛋糕(k≤M),使得其上的幸运值最大。
输入格式
输入文件cake.in的第一行是两个整数N,M。分别代表共有N小块蛋糕,小Z最多只能吃M小块。
第二行用空格隔开的N个整数,第i个整数Pi代表第i小块蛋糕的幸运值。
输出格式
输出文件cake.out只有一行,一个整数,为小Z能够得到的最大幸运值。
输入输出样例
输入 #1
5 2
1 2 3 4 5
输出 #1
9
输入 #2
6 3
1 -2 3 -4 5 -6
输出 #2
5
说明/提示
对20%的数据,N≤100。
对100%的数据,N≤500000,|Pi|≤500。 答案保证在2^31-1之内。
【思路】
【条件反射】
单调队列
看到这道题目想单调队列
第一时间想的是单调蛋糕的幸运值
【60分贪心解法】
单调队列 + 贪心
部分分解法
贪心
用一个ans记录目前队列里面的值
每一次都先把队列里面超出m长度范围的数弹掉
然后贪心
怎么个贪心法呢?
如果队列里面总值为正数那方就去一定比是负数更优
所以当里面总和为负数的话就弹出
直到为空或者为正数
就算是0也势必负数更优的
所以就可以一直比较最大值
水了60分
【部分分的局限性】
然后发现很有问题
因为有这种可能
-10 5 7
队列总和是2,正数
如果按贪心来的话那就会直接把下一个元素放进去
但是如果弹出队首的 -10 结果队列里面的总和会变为12
比原来贪心的2更优
所以用贪心这种情况是没有办法处理的
【正解】
既然单调单个蛋糕的幸运值是不行的
那换个思路想一下
这里面每个点前面连续小于等于m长度的区间最大值
是这个点到前面一个距离小于等于m长度的点中间的值
想一个O(1)求线性区间的方法?
这必然是前缀和!
因为想要这个区间最大
那么这个点到最优点总和要最大
可以用这个点的前缀和减去最优点的前缀和
因为这个点的前缀和是确定的
所以想让解法更优
那就只能让最优点的前缀和更小
这就会让差更大
所以可以单调前缀和
这样就很好搞出来咯!
【最后结论】
只需要单调前缀和
和滑动窗口的处理方式一样
deque或者数组就okoj
如果队首的到这个点的距离大于了m那就弹出
如果队尾的值大于将要放入的这个前缀和那就弹出
最后这个点的值和队首的差就是这个点的最优解
比较找最大值就好了
【注意】
要在弹出完比这个点的前缀和更大的点之后
先将这个前缀和放进去
然后在计算这个点和队尾的差
因为有可能整个队列中的数都比这个点的前缀和大
所以还不如不选!
30行的代码,60行的注释,就像老奶奶讲故事
【完整代码】
【贪心60分】
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int Max = 500005;
struct node
{
int v;
int hao;
}a[Max];
queue<node>q;
int main()
{
freopen("acioi.in","r",stdin);
int n,m;
cin >> n >> m;
for(register int i = 1;i <= n;++ i)
cin >> a[i].v,a[i].hao = i;
int ans = 0;
int M = 0;
for(register int i = 1;i <= n;++ i)
{
while(!q.empty() && i - q.front().hao >= m)
{
ans -= q.front().v;
q.pop();
}
while(!q.empty() && ans < 0)
{
ans -= q.front().v;
q.pop();
}
q.push(a[i]);
ans += a[i].v;
M = max(M,ans);
}
cout << M << endl;
return 0;
}
【单调队列——正解】
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int Max = 500005;
struct node
{
int t;
int w;
};
deque<node> q;
int main()
{
int n,m;
cin >> n >> m;
int ans = 0;
int x;
int M = 0;
for(register int i = 1;i <= n;++ i)
{
while(!q.empty() && i - q.front().t > m)
q.pop_front();
cin >> x;
ans += x;
while(!q.empty() && q.back().w > ans)
q.pop_back();
q.push_back((node){i,ans});
M = max(ans - q.front().w,M);
}
cout << M << endl;
}
洛谷 P1714 切蛋糕 题解的更多相关文章
- 洛谷 P1714 切蛋糕 单调队列
这个题比较显然,要用前缀和来做.但只用前缀和是过不去的,会TLE,所以需要进行优化. 对于每个前缀和数组 b 中的元素,都可以找到以 b[i] 结尾的子段最大值 p[i],显然,最终的 ans 就是 ...
- 【算法•日更•第六期】头脑风暴:洛谷P1528 切蛋糕题解
▎(一个没有用处的)前言 为什么这次题解特意写明题号呢?因为我发现了这样的事情: 所以不要混了,想看P1714题解的同志们可以圆润的滚开了. 好了,不说没用的了,切入正题: ▎题目 题目及测评链接:戳 ...
- [洛谷P1714]切蛋糕
题目大意:给你n个整数,求出其中长度不超过m的最大字段和. 题解:单调队列维护前缀和最小值,然后用当前值减去当前有效最小值即可 C++ Code: #include<cstdio> usi ...
- 洛谷—— P1714 切蛋糕
https://www.luogu.org/problem/show?pid=1714 题目描述 今天是小Z的生日,同学们为他带来了一块蛋糕.这块蛋糕是一个长方体,被用不同色彩分成了N个相同的小块,每 ...
- 洛谷P1714切蛋糕
题目 该题目就是求这n个数的前缀和所组成的数组的所有子区间的左端点和右端点相差不超过m,且他们的前缀和差最大,求出这个最大值即可. 而朴素算法肯定会T,而我们发现如果前缀和最大的话,则前缀和的值一定是 ...
- 洛谷P1714 切蛋糕(单调队列)
先放代码...... 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=5e5+10,M=0x3f3f3f3f; ...
- 洛谷P1577 切绳子题解
洛谷P1577 切绳子题解 题目描述 有N条绳子,它们的长度分别为Li.如果从它们中切割出K条长度相同的 绳子,这K条绳子每条最长能有多长?答案保留到小数点后2位(直接舍掉2为后的小数). 输入输出格 ...
- [洛谷P1528] 切蛋糕
洛谷题目链接:切蛋糕 题目描述 Facer今天买了n块蛋糕,不料被信息组中球球等好吃懒做的家伙发现了,没办法,只好浪费一点来填他们的嘴巴.他答应给每个人留一口,然后量了量每个人口的大小.Facer有把 ...
- 洛谷P1528 切蛋糕 [搜索,二分答案]
题目传送门 切蛋糕 题目描述 Facer今天买了n块蛋糕,不料被信息组中球球等好吃懒做的家伙发现了,没办法,只好浪费一点来填他们的嘴巴.他答应给每个人留一口,然后量了量每个人口的大小.Facer有把刀 ...
随机推荐
- AspNetCore Redis实现分布式缓存
分布式缓存描述: 分布式缓存重点是在分布式上,相信大家接触过的分布式有很多中,像分布式开发,分布式部署,分布式锁.事物.系统 等有很多.使我们对分布式本身就有一个很明确的认识,分布式就是有多个应用程序 ...
- 微信公众号 分享接口 签名通过 分享无效果(JSSDK自定义分享接口的策略调整)
为规范自定义分享链接功能在网页上的使用,自2017年4月25日起,JSSDK“分享到朋友圈”及“发送给朋友”接口,自定义的分享链接,其域名或路径必须与当前页面对应的公众号JS安全域名一致,否则将调用失 ...
- CCF 2016-12-1 最大波动
CCF 2016-12-1 最大波动 题目 问题描述 小明正在利用股票的波动程度来研究股票.小明拿到了一只股票每天收盘时的价格,他想知道,这只股票连续几天的最大波动值是多少,即在这几天中某天收盘价格与 ...
- springboot笔记06——使用Thymeleaf模板引擎
前言 Springboot 推荐使用Thymeleaf做视图层.Thymeleaf支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式.浏览器解释 html 时会忽略 ...
- Mycat分布式数据库架构解决方案--schema.xml详解
echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 该文件 ...
- Win10同时安装office2016和visio2016说明
前言 无论是先安装office2016还是visio2016,均不能成功. 而office2016和visio2016的镜像文件是一样的,只是名称不一样,只需下载其一即可. 具体参考链接 https: ...
- cloudera manager(CDH)实践
cloudera manager 可以简化 Hadoop 的安装配置过程,自动在集群节点上安 装 hadoop 相关组件,创建用户,并管理各个组件服务.本手册以 cloudera manager 的 ...
- Android笔记(三十七) 如何停止AsyncTask?
当我们加载一张图片的时候,加载的过程中我们想要取消操作,该怎么办呢?调用Asynctask的 cancel() 方法就可以了,我们看代码: 先看一个例子: MainAciticty.java pack ...
- simpleDateFormat中格式化时间需要注意的问题
student.getDateProperty("business","birth","yyyy-MM-dd",null)测试时 时间格式 ...
- python中 "is"和"=="的区别
python中"is"和"=="区别 在做leetcode的时候,在判断两个数据是否相等时使用了python中的is not,想着入乡随俗,既然入了python ...