AtCoder - ABC 161 - E(贪心)

E - Yutori

题意:

给你一个长度为 n 的字符串 s(仅由 ’x’ 和 ’o’ 组成),表示n天的上班状态,’o’ 表示该天上班;’x’ 表示不上班。要求总共上班 k 天,且两相邻上班时间之间至少隔 c 天。

输出无论怎么选一定要选的位置。

数据范围:

1 ≤ N ≤ 2×10^{5}

1 ≤ K ≤ N

0 ≤ C ≤ N

思路:

要找出哪一天必须工作,找出第 i 天工作的最早时间最晚时间,如果这两时间重合,就说明这一天必须工作。
实现:用两个数组 a,b 分别记录第 i 次工作开始的最早时间和最晚时间。要记录最早时间,就顺序遍历字符数组,工作次数 i 从1开始向后推,第一个满足条件且为'o'的就是第 i 次工作的最早时间;要找最晚时间,倒着看,逆序遍历字符串,工作次数 i 从k开始向前推。

Code:

#include
#include
using namespace std;

const int N = 200010;

int n, k, c;
char s[N];
int a[N], b[N];

void solve()
{
	cin >> n >> k >> c;
	cin >> (s + 1);

	//计算第i次工作的最早时间
	for(int i = 1,j = 1; i <= n && j <= k; i++)
		if (s[i] == 'o')
		{
			a[j++] = i;
			i += c;
		}

	//计算第i次工作的最晚时间
	for (int i = n, j = k; i > 0 && j > 0; i--)
		if (s[i] == 'o')
		{
			b[j--] = i;
			i -= c;
		}

	for (int i = 1; i <= k; i++)
		if (a[i] == b[i])              //如果第i次工作的最早时间与最晚时间相同,说明这天必须工作
			cout << a[i] << endl;
}

int main()
{
	int t = 1;
	//cin >> t;
	while (t--)
	{
		solve();
	}

	return 0;
}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
吐槽:贪心嘛,有思路好说,没思路就……害,本题注意点:

注意记录时间的方法:记录最早和时间顺序遍历数组找k个'o'还挺好理解,记录最晚时间则需要逆序遍历且i从k开始,记录k次即可。

你可能感兴趣的:(AtCoder,算法)