Hetao P1184 宝可梦训练家 [ 绿 ][ 背包dp ][ 线性dp ]


题解
一道超级牛逼的背包变形,想通之后真的很简单,难点在于想到使用 dp 并且用 dp 的值判断是否合法。
首先观察本题的数据范围:\(1\le n,q \le 10^5\) ,可知本题的询问要在 \(O(1) \text{~}O(\log n)\) 的时间里处理出来。
因此想到了二分或者预处理做法。
同时再来观察 \(k\) 的范围,\(1\le k \le 50\) ,这是个非常重要的切入点,同时把 \(a,l,r\) 的范围限制在 \(10^5+50\) 也是一个非常重要的条件。假设题目不需要利用这个条件,又为什么要将 \(k\) 限制在 \(50\) ,而不开到 \(10^9\) 呢?这就告诉我们题目的重点不在 \(n\) 上,重点是要计算每个宝可梦变成的值。
这样就可以直接排除二分区间应对询问的做法,因此直接考虑预处理。
分析
先考虑最简单的预处理方式:定义 \(f[i][j]\) 表示能否变成数字为 \([i,j]\) 的区间。
这种预处理方式不仅会 MLE ,而且会 TLE 。
但是我们也可以发现一个优化的点,那就是对于 \(f[i][j]=Yes\) 时,\(f[i+1][j] = Yes\) 。
同理,也可以说成是 \(f[i][j-1]=Yes\) ,只要换一种方式存储和写代码即可,这里采用上面的一种优化方案。
因此,我们用 \(f[j]\) 存储以数字 \(j\) 为结尾,最长能有的区间的长度 \(len\) ,那么此时的 \(i=j-len+1\)。所以当 $f[j] \ge j-i+1 $ 时,这个区间就可以得到($j-i+1 $ 是这个区间的长度),实际上,存储 \(i\) 来逆推 \(len\) 也不是不可以。
那么此时我们就只剩处理出 \(f[j]\) ,即以每个数字 \(j\) 结尾的 \(len\) 就行了。
建立模型
可以发现,\(f[j]\) 可以看成一个容量为 \(j\) 的背包,那么它的价值便是 \(len\) ,我们要使 \(len\) 最大化。并且由于每个宝可梦只能使用一次,所以这是个 01背包 。
所以设 $j=a[i]+v $ ,则 $ f[j]=f[j-1 ]+1$,其中 \(0\le v \le k\),即宝可梦的可以变换成的数。
这个方程的意义是:以 \(a[i]+v\) 为结尾时,最长的区间是从 以 \(a[i]+v-1\) 为结尾时最长区间的长度加了一个 \(1\) 得来的。
注意 01背包 的特殊转移方式,要让 \(v\) 从 \(k\) 到 \(0\) 转移,才能让使用了某个宝可梦的子集不包含也使用了这个宝可梦的子集。
唯一不同的是,背包加入物品是无序的,因为只要求 max 即可;但是这题加入是有序的,如果比它小的数没有更新完,而直接更新这个数,就会导致没有将这个状态分割成不遗漏也不重叠的子集,这是不行的。
因此,要先排个序再来给 \(f\) 更新。
时间 \(O(nk)\) 。
代码
#include <bits/stdc++.h>
using namespace std;
int f[100105],n,q,k,l,r,a[100005];
int main()
{
freopen("pokemon.in","r",stdin);
freopen("pokemon.out","w",stdout);
cin>>n>>k>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
{
for(int j=k;j>=0;j--)
{
f[a[i]+j]=f[a[i]+j-1]+1;
}
}
for(int i=1;i<=q;i++)
{
cin>>l>>r;
if(f[r]>=r-l+1)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
Hetao P1184 宝可梦训练家 [ 绿 ][ 背包dp ][ 线性dp ]的更多相关文章
- 2018.10.19 NOIP训练 变化的序列(线性dp)
传送门 f[i][j]f[i][j]f[i][j]表示后iii个对答案贡献有jjj个a的方案数. 可以发现最后a,ba,ba,b的总个数一定是n∗(n−1)/2n*(n-1)/2n∗(n−1)/2 因 ...
- 从0开始搭建精灵宝可梦的检测APP
从0开始搭建精灵宝可梦的检测APP 本文为本人原创,转载请注明来源链接 环境要求 Tensorflow1.12.0 cuda 9.0 python3.6.10 Android Studio Anaco ...
- Java反射:new一个宝可梦吧
最近写Spring Boot的测试用例会发现经常会有用到@RunWith(SpringRunner.class)的设置注解,关于SpringRunner.class的理解也有点似是而非.其实这种写法是 ...
- HDU6578 2019HDU多校训练赛第一场 1001 (dp)
HDU6578 2019HDU多校训练赛第一场 1001 (dp) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题意: 你有n个空需要去填,有 ...
- ZJNU 2135 - 小智的宝可梦
因为成环 所以可以枚举第1只与第n只喂的次数 然后第1只和第2只的次数就固定了,以此类推,则所有宝可梦喂的次数都固定了 最后处理完检查是否全为0,不是则进行下一次枚举,是则直接输出Yes 如果所有枚举 ...
- ALGO-31_蓝桥杯_算法训练_开心的金明(DP)
问题描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎 么布置,你说了算,只要不超过N元钱就行”.今 ...
- ALGO-13_蓝桥杯_算法训练_拦截导弹(贪心,DP)
问题描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...
- 2018.12.31 NOIP训练 czy的后宫6(线性dp)
传送门 题意简述:给一个nnn个数的数列,你可以把它最多分成mmm段,求每段数之和的最大值的最小值,以及满足这个最小值的时候划分数列的方案数. 思路:第一个问题是二分经典问题,不妨设其答案为limli ...
- 2018.11.06 NOIP训练 简单的计数问题(计数dp)
传送门 直接f[i][j]f[i][j]f[i][j]表示已经到第iii个位置已经找到jjj个的方案数. 简单转移一下就行了. 代码
- 2018.11.01 NOIP训练 树的排列(树形dp)
传送门 跟这道题差不多. 只不过是让权值小的儿子做权值大的儿子的父亲而已. 代码
随机推荐
- element table 合并同类项并输出后台返回数据
table的样式如下 后台返回的数据格式是按照横着来的,因为表头是经过处理的,而且是作为独立出来的数据返给前端的,所以当我们进行数据填充的时候需要用到后台返回的完整的数据,要想一一对应的话,我们需要进 ...
- echarts 的使用
<template> // option 通过id行绑定 <div id="myRangChart" style="width: 100%;he ...
- cmu15545笔记-WAL和数据库恢复
目录 总览 缓存策略(Buffer Pool Policies) Shadow Paging(No-Steal + Force) SQLite Rollback Mode(Steal + Force) ...
- 【Android】谷歌应用关机闹钟 PowerOffAlarm 源码分析,并实现定时开、关机
前言 RTC RTC 即实时时钟(Real-Time Clock),主要是功能有: 时间保持:RTC可以在断电的时候,仍然保持计时功能,保证时间的连续性 时间显示与设置:RTC可以向系统提供年.月.日 ...
- Spring Security并结合JWT实现用户认证(Authentication) 和用户授权(Authorization)
引言在Web应用开发中,安全一直是非常重要的一个方面.Spring Security基于Spring 框架,提供了一套Web应用安全性的完整解决方案. JwT (JSON Web Token) 是当前 ...
- Python 在Excel单元格中应用数据条
在Excel中添加数据条是一种数据可视化技巧,它通过条形图的形式在单元格内直观展示数值的大小,尤其适合比较同一列或行中各个单元格的数值.这种表示方式可以让大量的数字信息一目了然.本文将介绍如何使用Py ...
- 国外著名交易策略:R-Breaker模型设计原理(转载)
R-Breaker是一种短线日内交易策略,它结合了趋势和反转两种交易方式. 交易系统的基本原理如下: 1.根据前一个交易日的收盘价.最高价和最低价数据通过一定方式计算出六个价位,从大到小依次为:突破买 ...
- Qt开源作品20-PNG图片警告去除工具
一.前言 在新版的Qt5中,我们之前在Qt4中使用的png图片,到了这里经常会报一个警告,libpng warning: iCCP: known incorrect sRGB profile,尽管这种 ...
- Qt开源作品14-导航按钮控件
一.前言 导航按钮控件,主要用于各种漂亮精美的导航条,我们经常在web中看到导航条都非常精美,都是html+css+js实现的,还自带动画过度效果,Qt提供的qss其实也是无敌的,支持基本上所有的CS ...
- JAVA根据集合中属性判断是否包含元素
boolean isContain = list.stream().anyMatch(item -> item.getKey().equals(key));