Lilliput Steps

小さな一歩から着実に. 数学やプログラミングのことを書きます.

Codeforces 353D - Queue

問題文 : Queue

概要 :
長さ$n$ の文字列があり, 'M' と'F' から構成されている. 1 ターンの間に次の動作を行う :
"MF" という部分文字列を"FM" に置き換える.

文字列が"FF.....MM" という形になるのは何ターン後か?

$n \leqq 10^6$


解法 :

まず, 先頭にあるF は無視する. 最後のF 所定の位置に移動するまでの時間がわかれば良い.
とりあえず自分より前にあるM 以上のターンがかかるのは分かる. 問題は, 部分列を交換している間にどれくらい"待つ" 必要があるかということになる.
これは, max(前の人との距離 - 今までの待ち時間 + 1, 0) で求まる. これを$w$ とすると, 答えは$w$ + 自分の前にいる'M' の数になる.

先頭から確かめられるため$O(n)$ 時間でこの問題を解ける.

コード :

#include <cstdio>

using namespace std;

int main()
{
	static char s[1000001];
	
	scanf("%s", s);
	
	int ret = 0, w = 0, tmp = 0, tot = 0;
	for (int i = 0; s[i]; i++){
		if (s[i] == 'M'){
			tmp++; tot++;
		}
		else {
			w = max(w - tmp + 1, 0);
			if (tot) ret = tot + w;
			else w = 0;
			tmp = 0;
		}
	}
	printf("%d\n", ret);
	
	return (0);
}