题意:给你一个n个元素的数组,从中选取x个元素,并且要保证任意的m个位置中必须至少有一个元素被选中,问选中元素的和最大可以是多少?

F1 n,m,x到200 F2 n,m,x到5000。

思路1:设dp[i][j]为选择i位置的元素,并且包括i位置已经选择了j个元素,所有选中元素的最大和。

那么为了保证方案的合法性,只能从i-m+1的地方状态转移,dp[i][j]=max(dp[k][j-1])+a[i] (i-m+1<=k<i);,意思是找从i-m+1位置到i-1位置找已经选区j-1个元素中和最大的一个,在加上自己。

最后在n-m+1到i中找最大值就是答案,这些点因为已经被选取,所以保证了最终答案的合法性。

代码:

#include<bits/stdc++.h>
using namespace std;
long long dp[210][210],a[210];
int main(){
int n,m,x;
scanf("%d%d%d",&n,&m,&x);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
int tmp=n-(m-1);
if((tmp/m+(tmp%m!=0))>x){
printf("-1\n");
return 0;
}
int lim=1;
for(int i=1;i<=n;i++){
for(int j=lim;j<=min(i,x);j++){
for(int k=max(0,i-m);k<i;k++){
dp[i][j]=max(dp[k][j-1]+a[i],dp[i][j]);
}
}
if(i%m==0)lim++;
} long long ans=0;
for(int i=n-m+1;i<=n;i++)
ans=max(ans,dp[i][x]);
printf("%lld\n",ans);
}

思路2:现在数据规模变大了,原来的做法可以卡成O(n3),过不了。仔细观察状态转移过程,会发现有很多无用的状态,比如dp[i][j-1]<dp[k][j-1] (i<k),dp[i][j-1]这个状态肯定不会成为更新的跳板,于是我们就可以用单调队列优化。

外层循环枚举选取的元素个数,内层循环枚举数组的元素,用单调队列的队头更新最优解,此时dp[i][j]表示已经选区了i个元素,第j个元素已经被选的最优解,单调队列的队头出队过程保证了方案的合法性。

代码:

#include<bits/stdc++.h>
using namespace std;
long long dp[2][5010],a[5010];
int q[100010],l=1,r=0;
int main(){
int n,m,x;
scanf("%d%d%d",&n,&m,&x);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
int tmp=n-(m-1);
if((tmp/m+(tmp%m!=0))>x){
printf("-1\n");
return 0;
}
memset(dp,-0x3f,sizeof(dp));
dp[1][0]=0;
int now=0;
for(int i=1;i<=x;i++){
l=1,r=0;
q[++r]=0;
for(int j=1;j<=n;j++){
while(l<=r&&q[l]+m<j)l++;
dp[now][j]=dp[now^1][q[l]]+a[j];
while(l<=r&&dp[now^1][q[r]]<=dp[now^1][j])r--;
q[++r]=j;
}
now^=1;
}
now^=1;
long long ans=-1;
for(int i=n-m+1;i<=n;i++)
ans=max(ans,dp[now][i]);
printf("%lld\n",ans);
}

  

---恢复内容结束---

Codeforces 1077(F1+F2) DP 单调队列的更多相关文章

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

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

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

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

  3. DP+单调队列 codevs 1748 瑰丽华尔兹(还不是很懂具体的代码实现)

    codevs 1748 瑰丽华尔兹 2005年NOI全国竞赛  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Master 题解       题目描述 Descripti ...

  4. 习题:烽火传递(DP+单调队列)

    烽火传递[题目描述]烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有n个烽火台,每个烽火台 ...

  5. (noip模拟二十一)【BZOJ2500】幸福的道路-树形DP+单调队列

    Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...

  6. 3622 假期(DP+单调队列优化)

    3622 假期 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 黄金 Gold 题目描述 Description 经过几个月辛勤的工作,FJ决定让奶牛放假.假期可以在1-N天内任意选择 ...

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

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

  8. Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF980F.html 题目传送门 - CF980F 题意 给定一个 $n$ 个节点 $m$ 条长为 $1$ 的边 ...

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

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

随机推荐

  1. 奔跑吧,OpenStack现场分享:超融合架构如何抹平物理硬件差异?

    转自:https://www.ustack.com/blog/moping/ “通过引入OpenStack这一中间层,实现了云平台统一的管理调度支配向上交付,解决了业务的灵活性问题.但是在抹平下层物理 ...

  2. 16-THREE.JS 半球光

    <!DOCTYPE html> <html> <head> <title></title> <script src="htt ...

  3. 通过例子深入理解javascript中的new操作符

    1.首先看一道题目 function Cat(name,age){ this.name=name; this.age=age; } console.log(new Cat('miaomiao',18) ...

  4. /var/adm/wtmp文件太大该怎么办?

    /var/admin/wtmp文件记录所有用户的登陆信息,随着时间会增长到很大,/var/adm/wtmp文件太大该怎么办呢?先来看看/var/adm/wtmp文件的属性:testterm1:/#ls ...

  5. Spring mvc服务端消息推送(SSE技术)

    SSE技术是基于单工通信模式,只是单纯的客户端向服务端发送请求,服务端不会主动发送给客户端.服务端采取的策略是抓住这个请求不放,等数据更新的时候才返回给客户端,当客户端接收到消息后,再向服务端发送请求 ...

  6. Django上传文件的两种方式

    基于form表单上传文件 HTML <h3>基于form表单的上传文件</h3> <form action="" method="post& ...

  7. java入门学习(1)一简介及其基础特点

    分类: java基础 1.为什么java如此流行,为什么历史选择了它? 因为它拥有全新的编程思想,更接近人们的语言习惯,由于其编译器把代码编译成字节码,然后再不同的平台上运行分别用不同的虚拟机去解释字 ...

  8. UVA - 11925 Generating Permutations (思维,构造)

    给你一个长度为n(n<=300)的排列,有两种操作,第一种是交换前两个数,第二种是把第一个数放到最后,让你用不超过2n^2次的操作把一个初始为1-n升序的排列变为该排列. 一开始被紫薯蛋疼的翻译 ...

  9. LeetCode Longest Uncommon Subsequence II

    原题链接在这里:https://leetcode.com/problems/longest-uncommon-subsequence-ii/#/description 题目: Given a list ...

  10. mysql之 percona-xtrabackup 2.4.7安装(热备工具)

    准备:os是centos6.7,提前下载并上传 percona-xtrabackup 安装包,下载网址为: https://www.percona.com/downloads/XtraBackup/L ...