题目描述
题目描述
小易觉得高数课太无聊了,决定睡觉。不过他对课上的一些内容挺感兴趣,所以希望你在老师讲到有趣的部分的时候叫醒他一下。你知道了小易对一堂课每分钟知识点的感兴趣程度,并以分数量化,以及他在这堂课上每分钟是否会睡着,你可以叫醒他一次,这会使得他在接下来的k分钟内保持清醒。你需要选择一种方案最大化小易这堂课听到的知识点分值。
输入描述:
第一行 n, k (1 <= n, k <= 105) ,表示这堂课持续多少分钟,以及叫醒小易一次使他能够保持清醒的时间。
第二行 n 个数,a1, a2, … , an(1 <= ai <= 104) 表示小易对每分钟知识点的感兴趣评分。
第三行 n 个数,t1, t2, … , tn 表示每分钟小易是否清醒, 1表示清醒。
输出描述:
小易这堂课听到的知识点的最大兴趣值。
时间限制:1秒 空间限制:262144K
分析问题
这道题即使是暴力破解,本题的时间复杂度应为O(n2),我们能做的是优化算法来降低时间复杂度到o(n),通常采用的是用空间换时间的策略。
首先,我们可以观察暴力破解的运行过程,为依次计算每一分钟叫醒后可以获得的知识点分值。很容易发现,在这过程中有很大一部分是重复计算。比如,清醒时间内知识点分值是固定的。如果将清醒时间内知识点分值与被叫醒时间下知识点分值分开计算,那么时间复杂度将降为o(n+k*n),即O(k*n)。
接下来,把目光放在叫醒时间内的知识点分值的计算。同样的,每一分钟被叫醒时间内的知识点分值的计算在相邻的叫醒时间内有大量的重复计算。对于相邻时间下知识点分值的计算,完全可以只计算差异的部分,即多出来的被叫醒时间与少去的叫醒时间的知识点分值差。时间复杂度将降为o(n+n),即O(n)。
解决方案
首先,计算清醒时间下的知识点分值。
int wakingScore
for(int i=0;i<n;++i)
{
if(1==*(wake+i))
wakingScore+=*(know+i);
}
然后,计算第一分钟被叫醒获得的分数。
int awakenedScore=0
for(int i=0;i<k;++i)
{
if(0==*(wake+i))
{
awakenedScore+=*(know+i);
}
}
然后计算每分钟被叫醒后能获得的最大知识点分值。
maxScore=awakenedScore;
for(int i=k;i<n;++i)
{
if(0==*(wake+i))
{
awakenedScore+=*(know+i);
}
if(0==*(wake+i-k))
{
awakenedScore-=*(know+i-k);
}
if(awakenedScore>maxScore)
{
maxScore=awakenedScore;
}
}
最后,将清醒时间内的知识点分值与被叫醒时间内的分值相加就是本题的答案。
maxScore+=awakenedScore;
明天的题
又到了丰收的季节,恰逢小易去牛牛的果园里游玩。
牛牛常说他对整个果园的每个地方都了如指掌,小易不太相信,所以他想考考牛牛。
在果园里有N堆苹果,每堆苹果的数量为ai,小易希望知道从左往右数第x个苹果是属于哪一堆的。
牛牛觉得这个问题太简单,所以希望你来替他回答。