题目大意:给定一个长度为 N 的序列,点有点权,从序列中选出恰好 X 个数,并且保证任意连续的 K 个数中均有一个被选中,求选出的点权最大是多少。

题解:此题可以作为 烽火传递+ 来处理,只不过在烽火传递的基础上加了选出恰好 X 个数,因此只需在状态维度上加上一维选出的个数即可,\(dp[i][j]\) 表示前 i 个数中选出 j 个数,且第 i 个数被选中的最优解,因此有状态转移方程:\(dp[i][j]=max\{dp[k][j-1],k\in[i-m,i-1] \}+val[i]\),直接用单调队列进行优化即可。

同时,可以直接在初始化的时候将所有值设为无穷,避免了无效的状态转移,从而避免了不合法的解对答案的贡献,也就避免了讨论何时输出 -1 的问题。

代码如下

#include<bits/stdc++.h>
using namespace std;
const int maxn=5010; int n,m,tot,val[maxn],q[maxn<<1],l,r;
long long dp[maxn][maxn],ans; void read_and_parse(){
scanf("%d%d%d",&n,&m,&tot);
for(int i=1;i<=n;i++)scanf("%d",&val[i]);
} void solve(){
memset(dp,0xcf,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=tot;i++){
l=1,r=0;
for(int j=1;j<=n;j++){
while(l<=r&&q[l]<j-m)++l;
while(l<=r&&dp[j-1][i-1]>dp[q[r]][i-1])--r;
q[++r]=j-1;
dp[j][i]=dp[q[l]][i-1]+val[j];
}
}
ans=-1;
for(int i=n-m+1;i<=n;i++)ans=max(ans,dp[i][tot]);
printf("%lld\n",ans);
} int main(){
read_and_parse();
solve();
return 0;
}

最新文章

  1. PHP中的数据库一、MySQL优化策略综述
  2. PCA数据降维
  3. 关于iOS导航控制器隐藏和显示会出现返回键失效,导航栏标题动画异常
  4. ArcGIS AddIN开发之自定义鼠标样式
  5. csv大文件分割以及添加表头
  6. UWP开发入门(二十)——键盘弹起时变更界面布局
  7. Extjs读取本地下拉选框数据源,分为text和value,显示text,传值value
  8. Javascript 基础(一)
  9. Windows XP下安装和配置Apache2.2.22服务器+PHP5+Mysql5
  10. ios--集成支付宝钱包支付iOS SDK的方法与经验
  11. [大牛翻译系列]Hadoop(4)MapReduce 连接:选择最佳连接策略
  12. Android 获取天气预报
  13. 通过try、except和else的使用来使Python程序更加“强壮”
  14. [Javascript] lodash: memoize() to improve the profermence
  15. NoSql数据库使用
  16. Java URLClassLoader 和 ClassLoader类加载器
  17. thinkphp5.1 使用success();和error();要注意的点
  18. C#基础(203)实例方法和重载方法总结,构造方法与实例方法总结,this关键字
  19. 洛谷P4206 聪聪与可可
  20. python运算符优先级

热门文章

  1. 20155333 《网络对抗》Exp2 后门原理与实践
  2. POJ1159
  3. POJ1080
  4. adb连接不上手机的解决方案
  5. Phabricator 在 centos 系统下发送 Email的配置
  6. npm install —— 从一个简单例子,看本地安装与全局安装的区别
  7. [dx11]利用SpriteFont绘制中文--本地化文本
  8. Kafka高性能吞吐关键技术分析
  9. 三丰云使用记录--部署iis服务器
  10. Google C++ 编码规范