记最多公式

22 篇文章 1 订阅

题目

你和小军正在上一堂微积分的课。这堂课会持续 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;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值