http://codeforces.com/problemset/problem/590/A;
在CF时没做出来,当时直接模拟,然后就超时喽。
题意是给你一个0 1串然后首位和末位固定不变,从第二项开始到倒数第二项,当前的a[i]=(a[i-1],a[i],a[i+1])三项排序后的中间项,比如连续3项为
1 0 1,那么中间的就变为1,然后题目让你输出达到稳定状态时所需的最小步数,不能的话输出-1。
无论给你啥数列,都能达到稳态。所以不可能输出-1;
还有一开始就稳定不变,或经过几次变换而稳定的,就不会在变化了(感觉这句话是废话);
本题的关键就是要找在变的段 比如11010101011,在变的段为中间的0101010段,而这最小的步数为(7+1)/2=4步,可以发现每次变换都会使两边的边相同的加1;所以每次变化
两边都加一所以是要变化的个数加1除二。上面一次变换为11101010111,然后到最后都变为1(如果两侧为0则都变为0),因为每次变化的结果是每端都加一个与两端相同的。再举个要变化的为
偶数的例子看看有什么不同1101010.如果偶数的化要变的前一项和开始不改变那项是不一样的,所以变换步数为(4)/2;再根据上面的结论正好一半变的和要变的前一项一样
一半和开始不变的一样,所以最后结果为1111000;
上面所举的例子只是一段变化。我们要找的是所有要变化的段,然后找要变换的段的最长那段,也就是变化次数最多的,就为所求。
最后稳态可根据上面所给的方法求的,就是找到所有的段都用上面的变换。
下面给代码:
1 #include<stdio.h> 2 #include<algorithm> 3 #include<stdlib.h> 4 #include<iostream> 5 #include<string.h> 6 #include<math.h> 7 typedef long long ll; 8 using namespace std; 9 int a[500010]; 10 int b[500010];//最后稳态的数组 11 int main(void) 12 { 13 int flag[500010]= {0};//标记需要变化的数组 14 int x,y,z,i,j,k,p,q; 15 scanf("%d",&k); 16 for(i=0; i<k; i++) 17 { 18 scanf("%d",&a[i]); 19 } 20 b[0]=a[0];//首相不变 21 b[k-1]=a[k-1];//末项不变 22 for(i=1; i<k-1; i++) 23 { 24 if(a[i]==a[i-1]||a[i]==a[i+1]) 25 { 26 continue; 27 } 28 else 29 { 30 flag[i]=1; 31 } 32 }//标记需要变化的 33 flag[0]=0;//首相不变标记 34 flag[k-1]=0;//末项不变标记 35 int ans=0; 36 for(i=1; i<k-1;) 37 { 38 if(flag[i]) 39 { 40 int uu=i; 41 int xx=i; 42 while(flag[xx]) 43 { 44 xx++; 45 }//找变化段的长度 46 if((xx-uu)%2==0)//变化段为偶数的情况 47 { 48 ans=(xx-uu+1)/2>ans?(xx-uu+1)/2:ans;//ans中存最大的变化次数 49 for(j=uu; j<uu+(xx-uu)/2; j++) 50 { 51 b[j]=a[uu-1]; 52 } 53 for(j=(xx-uu)/2+uu; j<xx; j++) 54 { 55 b[j]=a[xx]; 56 57 } 58 } 59 else//变化段为奇数的情况 60 { 61 ans=(xx-uu+1)/2>ans?(xx-uu+1)/2:ans; 62 for(j=uu; j<xx; j++) 63 { 64 b[j]=a[xx]; 65 } 66 } 67 68 i=xx; 69 70 } 71 else if(flag[i]==0) 72 { 73 b[i]=a[i];//不变的直接按原位赋给b 74 i++; 75 } 76 77 78 } 79 printf("%d ",ans); 80 for(i=0; i<k-1; i++) 81 { 82 printf("%d ",b[i]); 83 } 84 printf("%d ",b[k-1]); 85 86 return 0; 87 88 }