「开灯问题」题解

开灯问题

        内存限制:256 MB    时间限制:1000 ms

题目描述

        房间中现有 n 枚灯泡,编号从 1 ~ n,自左向右排成一排。

        最初0时刻时,所有的灯都是关着的。

        在 k 时刻(1 ≤ k ≤ n),我们打开编号为 light[k] 这个灯。

灯的颜色要想变成蓝色,就必须同时满足下面两个条件:

  • 灯处于打开状态。
  • 排在它左侧的所有灯也都处于打开状态。

请返回能够让所有开着的灯变成蓝色的时刻数目 。

输出格式

        输出只有一个整数,表示能够让所有开着的灯变成蓝色的时刻数目 。

样例

        样例输入 

复制5
2 1 3 5 4

        样例输出         

复制3

        样例解释 1

                0表示关灯状态,1表示开灯状态,2表示蓝灯状态,过程如下:

复制1时刻:0 1 0 0 0
2时刻:2 2 0 0 0  
3时刻:2 2 2 0 0  
4时刻:2 2 2 0 1
5时刻:2 2 2 2 2  

                所有开着的灯都变蓝的时刻分别是2,3和5。

数据范围

  • 输入的数字都是整数。

  • n与light序列元素数量相同。

  • 1 ≤ k ≤ n。

  • 1 ≤ n ≤ 5*10^4。

  •  light是[1, 2, 3, …, n]的一个排列。

解法1:模拟

思路

1、定义一个数组light用于存放每个灯的状态(0表示关灯状态,1表示开灯状态,2表示蓝灯状态)

2、从头开始遍历数组,如果light[j]是开灯状态,也就是light[j] != 0,那么它就可以变为蓝灯状态,否则就直接跳出循环 

原理:

如果要light[x]变为蓝灯状态,light[1]到light[x]都要是开灯状态,所以就可以直接从头开始遍历数组,直到light[i]为关灯状态

3、接着遍历数组看后面的灯是否都为蓝灯或关灯状态(注意:这里不能从头遍历,否则就会时间超限),如果是则ans++

4、最后输出ans即可

代码

#include <bits/stdc++.h>
using namespace std;
#define MAX 50005

int light[MAX];//1、用于存放每个灯的状态(0表示关灯状态,1表示开灯状态,2表示蓝灯状态)

int main(){

    int n, ans = 0;
    scanf("%d", &n);

    for (int i = 1; i <= n; i++) {

    	int k, j;
    	scanf("%d", &k);

    	light[k] = 1;

    	for (j = 1; j <= n; j++){2、从头开始遍历数组
    		if (light[j] != 0) {//如果light[j]是开灯状态,也就是light[j] != 0
    			light[j] = 2;//那么它就可以变为蓝灯状态
			} else {
				break;//否则就直接跳出循环
			}
		}

		bool flag = false;
		for (; j <= n; j++) {//3、接着遍历数组看后面的灯是否都为蓝灯或关灯状态
			if (light[j] == 1) {
				flag = true;
				break;
			}
		}
		if (!flag) {//如果是则ans++
			ans++;
		}

	}

	printf("%d", ans);
    return 0;
}

解法2:比较最右边亮灯与一共亮灯数

思路

思路与解法1大体相似。

        既然只要是从左开始且连续的亮灯,就都可以变为蓝灯状态,那么我们就只需要保存最右侧的亮灯,以及一共亮灯的数量,如果他们相等,那么所有的亮灯都在左侧且连续,即都为蓝灯状态,ans++。

这样一来,我们就只需要在在输入的时候持续刷新最右侧亮灯的位置(maxn),并让maxn与一共亮灯的数量进行比较,又因为每输入一个数就会亮一盏灯,所有一共亮灯的数量即是循环变量 i ,如果maxn等于i,则说明所有亮灯均为蓝灯,ans++,最后输出ans即可。

代码

#include <bits/stdc++.h>
using namespace std;
int main(){
    int n, maxn = -1, ans = 0;
    scanf("%d", &n);

    for (int i = 1; i <= n; i++) {

    	int k;
    	scanf("%d", &k);

    	maxn = max(maxn, k);//持续刷新最右侧亮灯的位置

    	if (maxn == i) {
    		ans++;//如果最大值与一共亮灯数相等,则说明亮的灯都为蓝灯状态
		}

	}

	printf("%d",ans);
    return 0;
}

代码只是辅助,要了解思路。

革命靠自觉,尽量不要复制啊啊啊啊啊

最后,留下你的大拇指

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值