P10229 题解
题目分析
Marko 购买了一系列书籍,每本书都有一个吸引力值。他有限的时间内(
问题可以转化为如何选择阅读哪些书籍,以使得最终灵感值最大。由于书籍的吸引力按照从左到右单调不减的方式排列,因此我们应该尽可能跳过吸引力较小的书籍,以便能够阅读到后面吸引力更大的书籍。
思路
我们可以使用前缀和来快速计算阅读一段连续的书籍的吸引力之和。定义一个数组
接着采用贪心的思想来解决这个问题。具体步骤如下:
- 从
i=0 开始遍历,表示跳过i 本书。 - 计算在跳过
i 本书后,还能阅读多少本书,设为s 。 - 计算在跳过
i 本书后,最后一本能读的书的编号,设为l 。 - 根据前缀和数组计算阅读这些书籍的吸引力之和,即
p_l - p_i 。 - 更新
ans ,即取当前计算得到的吸引力之和与ans 中的较大者。
最后得出的
C++ 代码实现
#include<bits/stdc++.h>
using namespace std;
long long k[200010],p[200010]; // 定义吸引力数组和前缀和数组
int main()
{
long long n,t,a,b,ans=0; // 定义书的数量,阅读时间,完整阅读时间,阅读封面时间和最终结果
cin >> n >> t >> a >> b; // 输入书的数量,阅读时间,完整阅读时间和阅读封面时间
for(long long i=1;i<=n;i++)
{
cin >> k[i]; // 输入每本书的吸引力值
}
for(long long i=1;i<=n;i++)
{
p[i]=p[i-1]+k[i]; // 计算前缀和
}
for(long long i=0;i<=n;i++)
{
if(i*b>t) break; // 如果跳过前面的书的时间大于 t,就退出循环
long long s=(t-i*b)/a; // 计算跳过i之前的所有书,还能阅读的书的数量
long long l=min(n,s+i); // 计算跳过i之前的所有书,还能阅读到的书的编号,有时可能会大于 n,所以和 n 取最小值
ans=max(ans,p[l]-p[i]); // 更新最大灵感值
}
cout << ans << endl;
return 0;
}