题目链接:http://codeforces.com/problemset/problem/590/A
题目大意是给一个串,头和尾每次变换保持不变。
中间的a[i]变成a[i-1],a[i],a[i+1]的中位数,而且此题串是01串。
对于01串
0 0 0中位数是0
0 0 1中位数是0
0 1 1中位数是1
1 1 1中位数是1
所以
1、串中有两个相邻以上的0或者1是保持不变的。
2、会变的只有是两个1中间的0或者两个0中间的1。
但是到这里的话,虽然证明了肯定能变成稳定态,就算把相同数字分组模拟,给1010101010.....这种形式的话需要O(n)次才能稳定。自然不能模拟。。
由于条件2,发现如果两个满足1的串中间夹着0101这种间隔的串,那么这一段只有中间0101串会变化。
那么我只需要输入时分组,对于每两个满足1的串处理中间的0101串,然后取所有0101串变换的最大次数即为答案所要求。
然后考虑两个满足1的串:
两头是0或者两头是1是同一种情况:
1110101010111 ->变换4次得到1111111111111
一头是0一头是1:
111010101000->变换3次得到111111000000
然后就发现就是变换(中间串长度+1)/2次,得到的全1或0,或者一半1一半0。
然后写的时候要特殊考虑一下一开始全0或1,或者一半0一半1发情况。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <map> #include <queue> #include <string> #define LL long long using namespace std; const int maxN = 500005; int n, top; struct node { bool val; int num; }s[3][maxN]; void input() { top = -1; int u; for (int i = 0; i < n; ++i) { scanf("%d", &u); if (top == -1 || u != s[0][top].val) { top++; s[0][top].val = u; s[0][top].num = 1; } else s[0][top].num++; } } void work() { int run = 0, ttop = -1, from, cnt; for (int i = 0; i <= top; i++) { ttop++; s[1][ttop] = s[0][i]; if (i < top-1 && s[0][i+1].num == 1) { from = i; i++; while (s[0][i].num == 1 && i < top) i++; if (s[0][from].val == s[0][i].val) { cnt = i-from+1; ttop++; s[1][ttop].val = s[0][i].val; s[1][ttop].num = cnt-2; run = max(run, cnt/2); } else { cnt = i-from+1; ttop++; s[1][ttop].val = s[0][from].val; s[1][ttop].num = cnt/2-1; ttop++; s[1][ttop].val = s[0][i].val; s[1][ttop].num = cnt/2-1; run = max(run, cnt/2-1); } i--; } } printf("%d ", run); bool flag = false; for (int i = 0; i <= top; ++i) { for (int j = 0; j < s[1][i].num; ++j) { if (flag) printf(" "); printf("%d", s[1][i].val); flag = true; } } printf(" "); } int main() { //freopen("test.in", "r", stdin); while (scanf("%d", &n) != EOF) { input(); work(); } return 0; }