codevs 3327 选择数字
3327 选择数字
给定一行n个非负整数a[1]..a[n]。现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择。你的任务是使得选出的数字的和最大。
第一行两个整数n,k
以下n行,每行一个整数表示a[i]。
输出一个值表示答案。
5 2
1
2
3
4
5
12
对于20%的数据,n <= 10
对于另外20%的数据, k = 1
对于60%的数据,n <= 1000
对于100%的数据,1 <= n <= 100000,1 <= k <= n,
0 <= 数字大小 <= 1,000,000,000
第一步:dfs
20分 TLE
#include<cstdio>
#include<algorithm>
using namespace std;
int n,k;
long long ans;
long long a[];
void dfs(int now,long long sum,int con)
{
if(now==n)
{
ans=max(ans,sum);
return;
}
for(int i=now+;i<=n;i++)
{
if(con<k) dfs(i,sum+a[i],con+);
dfs(i,sum,);
}
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
dfs(,,);
printf("%lld",ans);
}
这种写法好像不能改记忆化搜索
第二步:朴素的DP
唉,这一步也想不出来
看的那篇题解里写着一句话:人傻就要多做题
90分TLE 应该是数据弱。。。
不能有超过连续的k个数字被选择,所以第i个状态可以由第i-k到i的状态更新而来
定义f[i]表示选到第i个数字的最大和
在i-k——i这段长为k+1的序列中,必须有一个断点
枚举断点j
状态转移方程:f[i]=max(f[j-1]+sum[i]-sum[j]) i-k<=j<=i
#include<cstdio>
#include<algorithm>
using namespace std;
int n,k;
long long a[],f[],sum[];
int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++) scanf("%lld",&a[i]),sum[i]=sum[i-]+a[i];
for(int i=;i<=k;i++) f[i]=f[i-]+a[i];
for(int i=k+;i<=n;i++)
for(int j=i-k;j<=i;j++)
f[i]=max(f[i],f[j-]+sum[i]-sum[j]);
printf("%lld",f[n]);
}
开始做的时候 j只枚举到i-1,忽略了选i-k——i-1这段长为k的序列的情况
第三步:
单调队列优化DP
观察状态转移方程,交换后两项顺序:f[i]=max(f[j-1]-sum[j]+sum[i])
当i固定式,sum[i]固定,所以f[i]只与j有关
所以可以用一个单调递减的队列维护f[j-1]-sum[j]的最大值,
f[i]=队首(f[j-1]-sum[j]的最大值)+sum[i]
#include<cstdio>
#include<algorithm>
using namespace std;
int n,k,head,tail;
long long a[],f[],sum[],d[],q[];
int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++) scanf("%lld",&a[i]),sum[i]=sum[i-]+a[i];
for(int i=;i<=n;i++)
{
d[i]=f[i-]-sum[i];
while(head<tail&&q[head]<i-k) head++;
while(head<tail&&d[i]>d[q[tail-]]) tail--;
q[tail++]=i;
f[i]=d[q[head]]+sum[i];
}
printf("%lld",f[n]);
}
codevs 3327 选择数字的更多相关文章
- codevs3327选择数字(单调队列优化)
3327 选择数字 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 给定一行n个非负整数a[1]..a[n].现 ...
- P2034 选择数字
P2034 选择数字 题目描述 给定一行n个非负整数a[1]..a[n].现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择.你的任务是使得选出的数字的和最大. 错误日志: longlong ...
- input只读属性 设置和移除 选择数字
设置只读属性 $('#stage').attr("readonly", "readonly"); 移除 只读属性 $("input").r ...
- 科普:为什么 String hashCode 方法选择数字31作为乘子
作者:coolblog 此文章转载自:https://segmentfault.com/a/1190000010799123 1. 背景 某天,我在写代码的时候,无意中点开了 String hashC ...
- P2034 选择数字——线性dp(单调队列优化)
选择数字 题目描述 给定一行 \(n\) 个非负整数 \(a[1]...a[n]\) .现在你可以选择其中若干个数,但不能有超过 \(k\) 个连续的数字被选择.你的任务是使得选出的数字的和最大. 输 ...
- 「单调队列优化DP」P2034 选择数字
「单调队列优化DP」P2034 选择数字 题面描述: 给定一行n个非负整数a[1]..a[n].现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入格 ...
- 选择数字(codevs 3327)
题目描述 Description 给定一行n个非负整数a[1]..a[n].现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入描述 Input De ...
- P2034 选择数字 / P2627 [USACO11OPEN]Mowing the Lawn G
Link 题目描述 给定一行 \(n\) 个非负整数 \(a[1]..a[n]\) .现在你可以选择其中若干个数,但不能有超过 \(k\) 个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入 ...
- Codevs 4829 [DP]数字三角形升级版
4829 [DP]数字三角形升级版 时间限制: 1 s 空间限制: 16000 KB 题目等级 : 黄金 Gold 题目描述 Description 从数字三角形的顶部(如图,第一行的5表示行数)到底 ...
随机推荐
- b7
组员:陈锦谋 过去两天完成了哪些任务: 细节最后完善 明日计划: 无 还剩下哪些任务: 无 有哪些困难: 暂无 有哪些收获和疑问: 无
- 灵悟礼品网上专卖店——第三阶段Sprint
一.小组成员: 洪雪意(产品负责人) 陈淑筠(Master) 二.组内人员任务情况 已完成的任务: 陈淑筠:主页面的设计 洪雪意:导航条的改进和页面中插入页面的功能 正在进行的任务: 陈淑筠:主页面的 ...
- Python库moviepy
目录 介绍和下载安装 视频截取和拼接 视频加水印
- HTML常用标签及约束
注释 <!--这是一段注释--> 样式表 外部样式(CSS) <head> <link rel="stylesheet" type="tex ...
- 个人作业week3案例分析
调研产品:博客园 第一部分 调研和评测 1.bug 1.不同种类浏览器的支持存在差异 bug描述:在不同浏览器下,部分博客内容显示的格式有明显不同 可尝试用下面两种不同的浏览器打开这个博客网址:htt ...
- Oracle Instant Client
下载地址: https://www.oracle.com/technetwork/database/database-technologies/instant-client/downloads/ind ...
- ACM数论之旅3---最大公约数gcd和最小公倍数lcm(苦海无边,回头是岸( ̄∀ ̄))
gcd(a, b),就是求a和b的最大公约数 lcm(a, b),就是求a和b的最小公倍数 然后有个公式 a*b = gcd * lcm ( gcd就是gcd(a, b), ( •̀∀•́ ) ...
- 在输入密码框中眼睛睁开可以看见数字,眼睛闭上看不见数字怎么用JS实现
无论做那个项目,登录注册页面总是避免不了的,那怎么用js来控制密码的显示和隐藏呢?先看一下效果图: HTML代码如下: <div> <label for=" ...
- CodeForces - 988D(思维STL)
原文地址:https://blog.csdn.net/weixin_39453270/article/details/80548442 博主已经讲的很好了 题意: 从一个序列中,选出一个集合,使得集合 ...
- Powerful array CodeForces - 86D(莫队)
给你n个数,m次询问,Ks为区间内s的数目,求区间[L,R]之间所有Ks*Ks*s的和.1<=n,m<=200000.1<=s<=10^6 #include <iostr ...