[USACO07MAR] Face The Right Way G

2.6k 词

题目描述

DESCRIPTION

Farmer John has arranged his NN (1N5,0001 \leq N \leq 5,000) cows in a row and many of them are facing forward, like good cows. Some of them are facing backward, though, and he needs them all to face forward to make his life perfect.

Fortunately, FJ recently bought an automatic cow turning machine. Since he purchased the discount model, it must be irrevocably preset to turn KK (1KN1 \leq K \leq N) cows at once, and it can only turn cows that are all standing next to each other in line. Each time the machine is used, it reverses the facing direction of a contiguous group of KK cows in the line (one cannot use it on fewer than KK cows, e.g., at the either end of the line of cows). Each cow remains in the same *location* as before, but ends up facing the *opposite direction*. A cow that starts out facing forward will be turned backward by the machine and vice-versa.

Because FJ must pick a single, never-changing value of KK, please help him determine the minimum value of KK that minimizes the number of operations required by the machine to make all the cows face forward. Also determine MM, the minimum number of machine operations required to get all the cows facing forward using that value of KK.

INPUT FORMAT

Line 11: A single integer: NN

Lines 2..N+12..N+1: Line i+1i+1 contains a single character, F or B, indicating whether cow ii is facing forward or backward.

OUTPUT FORMAT

Line 11: Two space-separated integers: KK and MM

SAMPLE INPUT

1
2
3
4
5
6
7
8
7
B
B
F
B
F
B
B

SAMPLE OUTPUT

1
3 3

HINT

For K=3K = 3, the machine must be operated three times: turn cows (1,2,3)(1,2,3) , (3,4,5)(3,4,5), and finally (5,6,7)(5,6,7)

题目大意

NN 头牛排成一列 1N50001 \le N \le 5000。每头牛或者向前或者向后。为了让所有牛都面向前方,农夫每次可以将 KK 头连续的牛转向 1KN1 \le K \le N,求使操作次数最小的相应 KK 和最小的操作次数 MMFF 为朝前,BB 为朝后。

请在一行输出两个数字 KKMM,用空格分开。

题解

因为一个点翻转两次和没有翻转的效果相同,所以对于每个点而言,只有 不翻转翻转一次 两种可能性,将原序列的 BF 分别抽象为 01 ,构成01序列 AA ,对第ii的翻转操作就相当于 Ai1A_i \oplus 1 .

考虑贪心,顺序遍历每一位,如果当前位为 0 ( B ),则将以该位为起点,长度为KK的子串全部翻转,判断是否能够将AA的每一位置为 1 ( F ).

同时我们可以发现,使操作次数最小的相应 KK 和最小的操作次数 MM 并不具有单调性,只能通过枚举取得最优值,这样的时间复杂度是 O(n3)O(n^3) 并不能通过此题,必须再优化一维.

注意到贪心的过程中,我们对序列 AA 进行的是 区间修改单点查询 的操作,同时异或运算支持前缀和的操作,这里可以使用差分进行优化,这样时间复杂度就能降到 O(n2)O(n^2) 了.

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 5;

int n;
char ch;

bool a[N], d[N];

int main()
{
ios::sync_with_stdio(false);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> ch;
a[i] = ch == 'F';
}
int k, m = INT_MAX;
for (int l = 1; l <= n; l++)
{
memset(d, 0, sizeof(d));
bool sum = 0, flag = true;
int cnt = 0;
for (int i = 1; i <= n; i++)
{
sum ^= d[i];
if (a[i] ^ sum)
continue;
if (i + l - 1 > n)
{
flag = false;
break;
}
sum ^= 1;
d[i + l] ^= 1;
cnt++;
}
if (flag)
{
if (m > cnt)
{
m = cnt;
k = l;
}
}
}
cout << k << " " << m << endl;
return 0;
}