分析:
如果原序列中有两个相邻的0,或者两个相邻的1的话,那么这两个1(或者0)无论多少次变化,都不会发生改变,只有这种情况:1,0,1或者0,1,0。一个一个隔开来的数才会发生变化。那么将原序列分堆,连续的相同的数分在一堆,那么最后剩下来的序列为0,1,0,1,0,。。。(1,0,1,0。。。)这种形式,需要找的是相邻两个个数都不为1的堆之间长度为多少。
如果这两个堆是0开始1结束,那么中间的数最后被分成0,0,0,0,1,1,1,1这种形式,需要的步数是(两个堆之间长度)/2,同理1开始,0结束。不同情况:0开始,0结束,需要的步数是(两个堆之间长度+1)/2。最终都变成了0,0,0,…,0。同理:1开始1结束。
这题写起来我感觉还是比较麻烦,边界比较多,如果在a[0]之前添加一个数a[0],a[n-1]后面添加一个数位a[n-1],这样会简单很多。
#include <bits/stdc++.h>
#define LL long long
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
using namespace std;
const int maxn = 500050;
int a[maxn],b[maxn],c[maxn],n;
void work(){
b[0] = 0;
c[++b[0]] = a[1];
b[1] = 2;
FOR(i,2,n+1){
if(a[i] != a[i-1]){
b[++b[0]] = 1;
c[b[0]] = a[i];
}
else ++ b[b[0]];
}
++ b[b[0]];
int ans = 0;
int st = 1;
FOR(i,1,b[0]+1){
if(b[i] > 1){
ans = max(ans,(i-st)/2);
int len = (i-st)/2;
FOR(j,st+1,st+len+1) c[j] = c[st];
FOR(j,st+len+1,i) c[j] = c[i];
st = i;
}
}
printf("%d\n",ans);
-- b[1];
-- b[1];
-- b[b[0]];
printf("%d",c[1]);
FOR(i,1,b[0]+1){
FOR(j,0,b[i]){
printf(" %d",c[i]);
}
}
printf("\n");
}
int main(){
//freopen("test.in","r",stdin);
while(~scanf("%d",&n)){
FOR(i,1,n+1) scanf("%d",&a[i]);
work();
}
return 0;
}