题目
你和小军正在上一堂微积分的课。这堂课会持续 m
分钟,并且在第 i
分钟之内教授会讲授𝑎𝑖
个公式。小军虽然对微积分很感兴趣,但是由于他昨晚没有睡好,所以偶尔会打瞌睡。给出一个长度为 m
的数组 t
,如果为 1
,表示小军在第 i
分钟之内是清醒的;如果为 0
,表示小军在第 i
分钟之内是睡着的。当小军是清醒的时候,他会记下这分钟内教授讲授的所有公式;但是他睡着了就是睡着了,什么事情也不会干。你有一个技巧,可以让小军连续 k
分钟都保持清醒。但是这个技巧你只能使用一次,你可以在第 1
到第 m-k+1
的任意一分钟的开始时刻使用这个技巧。如果你在某一分钟如第 i
分钟的开始时刻使用了这个技巧,那么小军将会在第 j
分钟内保持清醒并且记下所有的公式,j
满足(i <= j <= i + k - 1)
。你的任务是在合适的时候使用这个技巧,使得小军可以记最多的公式,请你编程帮他计算出最多能记下多少公式。(程序运行要求,时间:2sec/
空间:256MB
)
输入
第一行两个整数 m 和 k,含义如题。
第二行 m 个整数,表示教授每分钟教授的公式的数量。
第三行 m 个整数,表示小军每分钟的状态,为 1 是清醒的,为 0
则睡着了。
满足 1 <= k <= m <= 105
。
输出
一个整数,表示小军记下的最多的公式的数量。
样例
输入
6 3
2 3 5 2 5 3
1 1 0 1 0 0
输出
17
#include <iostream>
#include <cstdio>
using namespace std;
//#define DEBUG
const int N = 1e+5;
struct Node {
int num; // 公式数量
int status; // 状态:0--睡觉,1--清醒
} node[N + 10];
int main() {
// freopen("in.txt", "r", stdin);
int m, k; // m:每分钟公式的数量,k:保持清醒的时间
cin >> m >> k;
for (int i = 0; i < m; i++) {
cin >> node[i].num;
}
for (int i = 0; i < m; i++) {
cin >> node[i].status;
// 转换状态,方便之后计算连续保持清醒k分钟时的最大值
node[i].status = 1 - node[i].status;
}
#ifdef DEBUG
for (int i = 0; i < m; i++) {
printf("%d-->%d\n", node[i].num, node[i].status);
}
#endif
int sum = 0, max = 0, max_index;
for (int i = 0; i < m - k + 1; i++) {
for (int j = i; j < i + k; j++) {
// printf("%d-->%d\n", node[j].num, node[j].status);
sum += node[j].num * node[j].status;
}
// printf("sum[%d]=%d\n", i, sum);
if (sum > max) {
max = sum;
max_index = i;
}
sum = 0;
}
// printf("%d==>%d\n", max_index, max);
for (int i = max_index; i < max_index + k; i++) {
node[i].status = 0;
}
for (int i = 0; i < m; i++) {
// 之前录入信息时将状态倒置了的,所以此处是和0比较:0--清醒,1--睡觉
if (node[i].status == 0) {
sum += node[i].num;
}
}
cout << sum << endl;
return 0;
}
超时,改:在输入时就进行数据的处理,避免后期大数据爆炸
参考链接:https://blog.csdn.net/m0_46297777/article/details/105617741
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e+5;
struct Node
{
int num; // 公式数量
int status; // 状态:0--睡觉,1--清醒
} node[N + 10];
long missed_sum[N + 10]; // 统计到第i分钟总共错失的公式数量
int main()
{
std::ios::sync_with_stdio(false);
memset(missed_sum, 0, sizeof(missed_sum));
int m, k; // m:课堂持续分钟,k:保持清醒的时间
cin >> m >> k;
for (int i = 1; i <= m; i++)
{
cin >> node[i].num;
}
long long sub_sum = 0;
for (int i = 1; i <= m; i++)
{
cin >> node[i].status;
if (node[i].status == 1)
{
sub_sum += node[i].num; // 统计保持清醒时所记住的公式数
missed_sum[i] = missed_sum[i - 1]; // 更新该节点之前所有没有记住的公式总数
}
else // 睡觉情况下该节点及之前没有记住的公式总数
{
missed_sum[i] = missed_sum[i - 1] + node[i].num;
}
}
long max_sum_sum = -1;
for (int i = 1; i <= m - k + 1; i++)
{
// i分钟没有记住的公式数:missed[i+k-1]-missed[i-1](用集合画图一下就理解了)
max_sum_sum = max(max_sum_sum, missed_sum[i + k - 1] - missed_sum[i - 1]);
}
cout << max_sum_sum + sub_sum << endl;
return 0;
}