51nod 1645 中位数变换

题目来源: CodeForces
基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
 收藏
 关注

有一个数列 a1, a2, ..., an  ,现在用这个数列来构造 b1, b2, ..., bn ,构造方法如下:

·         b1 = a1,bn = an ;

·        对于 i = 2, ..., n1 ,  bi  是  ai1, ai  ai+1 这三个数字的中位数。

三个数字的中位数是指把他们进行从小到大排序之后,摆在中间的数字。比如5, 1, 2的中位数是2,而1,0,1的中位数是1。

为了使问题简单一些,现在的数列中只包含0和1两种数字。

现在要对一个给定的序列做上述算法若干次,直到执行该算法后序列保持不变为止。保持不变的序列叫做稳定序列。

请输出最少要执行几次上述算法,才能达到稳定序列,最后的稳定序列是什么形态的。

样例解释:

在第二个样例中,变换的步骤是:  01010  00100  00000 。


Input
单组测试数据。
第一行有一个整数n (3≤n≤500000) ,表示序列的长度。
第二行有n个整数a1, a2, ..., an (ai = 0 或 1)。
Output
如果序列不能达到稳定状态,输出-1。
否则,第一行输出最少要几次才能达到稳定状态。
第二输出达到稳定状态后的序列是什么样的。
Input示例
样例输入1
4
0 0 1 1
样例输入2
5
0 1 0 1 0
Output示例
样例输出1
0
0 0 1 1
样例输出2
2
0 0 0 0 0

题解:我真是太水了连cf的div1的t1都想不出来QwQ

点击打开链接

  1. 【分析】 
  2. 对于比较新颖的有一定变换规则的题目,最好的上手方式是模拟样例以及观察。 
  3. 这题中,相邻的三个数的状态可能性其实只有如下8种: 
  4. 000->000 
  5. 001->001 
  6. 010->000 ! 
  7. 011->011 
  8. 100->100 
  9. 101->111 ! 
  10. 110->110 
  11. 111->111 
  12. 而在其中,只有标注!的两种发生了前后变换。 
  13. 我们发现,这个变换的条件也可以说是两头相同,中间夹一个不同的,然后中间这个就会变得和两头相同。 
  14. 而如果不是这样,只要存在相邻两个数是相同的,那么以它们任意一个数为中心,构成的三个数的中位数就必然是其本身,不会再发生变更。 
  15.  
  16. 于是我们就找所有10101……这样交替的区间段。 
  17. 对于一个长度为len的区间段,变换次数为(len-1)/2; 
  18. 如果len为奇数,那么最终整个区间都会变得和左右端点一样, 
  19. 如果len为偶数,那么左边一半和左端点一样,右边一半和右端点一样。 
  20.  
  21. 这样就可以AC啦 
  22.  
  23. 【时间复杂度&&优化】 
  24. O(n) 


事实证明51nod千万别用万能头文件!!!(时间爆炸,前后相差了10多倍)


代码:

#include<stdio.h>  
#include<string.h>  
#include<ctype.h>  
#include<math.h>  
#include<iostream>  
#include<string>  
#include<set>  
#include<map>  
#include<vector>  
#include<queue>  
#include<bitset>  
#include<algorithm>  
#include<time.h>  
using namespace std;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int a[1000001],ans,n;
int pd(int l,int r){
	if(r-l<2)return 0;
	int i,mid=(l+r)/2;
	for(i=l+1;i<=mid;i++)a[i]=a[l];
	for(i=mid+1;i<=r;i++)a[i]=a[r];
	return (r-l)/2;
}
int main(){
	int i,l;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		a[i]=read();
	}
	l=1;
	for(i=2;i<=n;i++){
		if(a[i]==a[i-1]){
			ans=max(ans,pd(l,i-1));
			l=i;
		}
	}
	ans=max(ans,pd(l,n));
	printf("%d\n",ans);
	for(i=1;i<=n;i++)printf("%d ",a[i]);
}

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页