codeforces#327-C.Median Smoothing-规律题
2015-10-26 19:24
127 查看
题意:
给定一个01串,每次操作后除首尾两个数字外所有数a[i]都变为(a[i-1]+a[i]+a[i+1])/2,问至少需要多少次操作才能使数字不再变化.输出操作次数及最终的结果.观察发现连续的n个0或1,是不会变化的(n>=2),也就是说只有单独的0或1才会变化,也就是只有:010101这样的串才会变化
并且 我们已经知道了,只有单独的01交替串才会变化
那么对于一个我们找到的01交替串 X0 1 0 1 0 1 0 1Y 假设我们找到的是X与Y中间部分,也就是说,每一次变化,他们之间的每一个数都会翻转,
翻转前X与该串的第一个字符肯定不等,翻转后他们必然相等, 同理Y那端也是一样的,也就是说,每翻转一次,这个不合法的01交替串的最两端的字符就会变为稳定状态(与X\Y一样了)
因此 对于一个01交替串,需要做的变换操作次数就是 (len+1)/2;
并且,如果XY相等,则整个子串会转为X/Y; (len必为奇数,因为 X 0 1 0 1 Y ,这种情况Y必与X不等)
如果不相等,可由前面推理知道,整个子串的稳定字符是有端点不断蔓延至中心,所以前1/2是X,后1/2是Y; (len必为偶数,因为 X 0 1 0 Y ,这种情况Y必与X相等)
若子串长度len为奇数,即首尾数字相同的,该子串变为同样长度,与首尾数字一致的串,如10101变为11111,而01010变为00000,需要的操作次数为len/2
若子串长度len为偶数,即首尾数字不同,子串中每个数字会变为与首尾数字中与其距离较近的一个,如101010变为111000,而01010101变为00001111,需要的操作次数为len/2-1
故而只要找出所有01交替的子串,将其修改,并取操作次数最大值即可.
题解参考自http://blog.csdn.net/lincifer/article/details/49422779
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> #include <set> #include <vector> using namespace std; int tm[500005]; int ans[500005]; int main() { int i,j,k; int n; scanf("%d",&n); for (i=1;i<=n;i++) { scanf("%d",&tm[i]); } ans[1]=tm[1]; ans =tm ; int maxx_dis=0; int dis=0; for (i=1;i<=n;i++) { for (j=i;j<=n-1;j++) { if (tm[j]==tm[j+1]) break; } dis=j-i-1; for (k=i;k<=j;k++) { if (k-i<j-k) ans[k]=tm[i]; else ans[k]=tm[j]; } if (maxx_dis<dis) maxx_dis=dis; i=j; } if (maxx_dis<dis) maxx_dis=dis; printf("%d\n",(maxx_dis+1)/2); // printf("%d\n",(maxx_dis+1)/2); for (i=1;i<=n;i++) { if (i!=1 ) printf(" "); printf("%d",ans[i]); } printf("\n"); return 0; }
相关文章推荐
- 有关802.11协议
- C++,JAVA之间相互调用学习
- #在蓝懿学习iOS的日子#Day5
- 记使用linux命令行编译c语言步骤
- 局部变量和成员变量的区别
- bfprt算法----找出数组中最小的k个数(Java)
- http状态码详解
- python property
- shell条件判断小知识
- poj 3080(后缀数组)
- document.createElement()的用法
- XVWA黑客靶场发布
- 数据结构_不带头结点的链表逆制
- DownFile
- C# 关键字
- C++:类的组合
- 第六周数据结构实践——后缀表达式(栈)【项目5 - 后缀表达式】
- POJ 3050 Hopscotch
- 《程序员面试金典》--寻找二叉树中两个节点的第一个公共祖先(三种情况)
- How to create a bootable USB stick on Windows