持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情。
题目信息描述
一天可以被分为 nn 个时段。
一个工人的每日工作安排可以用一个长度为 nn 的 0101 序列 a1,a2,…,ana1,a2,…,an 来表示。
aiai 为 00 表示第 ii 个时间段是工作时间,aiai 为 11 表示第 ii 个时间段是休息时间。
工人日复一日的严格按照这个工作安排来进行工作和休息。
请问,工人的最长连续休息时间有多长(单位:时段)?
注意,连续休息时间可能跨天。
保证工人至少在一个时间段处于工作状态。
输入格式
第一行包含整数 TT,表示共有 TT 组测试数据。
每组数据第一行包含整数 nn。
第二行包含 nn 个整数 a1,a2,…,ana1,a2,…,an。
输出格式
每组数据输出一行结果,表示最长连续休息时间。
数据范围
1≤T≤101≤T≤10, 1≤n≤2×1051≤n≤2×105, 0≤ai≤10≤ai≤1, 同一测试点内所有 nn 的和不超过 2×1052×105。
输入样例:
4
5
1 0 1 0 1
6
0 1 0 1 1 0
7
1 0 1 1 1 0 1
3
0 0 0
输出样例:
2
2
3
0
思路
既然可以跨天,那就直接构造一个n*2的数组存两次,这道题就解出来了。或者可以这样理解这道题目,它其实就是环形区间找最长连续1的个数,只要断环为链即可。存数据,如果最后一个数据是1,就从后往前遍历获取可以连接的时间,然后把这个数值存入第一个时间,再从头开始找最大长度。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int T;
int f[200050];
int main()
{
cin >> T;
while(T -- ){
int n;
cin >> n;
memset(f, 0, sizeof(f));
for(int i = 0; i < n; ++i){
cin >> f[i];
}
int count = 0;
if(f[n - 1] == 1){
for(int i = n - 1; ;--i ){
int j = i - 1;
while(f[j] == 1)j--;
count = i - j;
break;
}
}
if(f[0])f[0] += count;
int ans = 0;
for(int i = 0; i < n; ++i){
if(f[i] >= 1){
int j = i + 1;
while(f[j] == 1)j++;
ans = max(ans,f[i] + j - i - 1);
i = j;
}
}
cout << ans << endl;
}
return 0;
}