【NOIP2015模拟10.30晚】JZOJ7月27日提高组T1 中位数

【NOIP2015模拟10.30晚】JZOJ7月27日提高组T1 中位数

题目

在这里插入图片描述

题解

题意

定义一种操作:平滑化—— b n = f ( a n ) b_n=f(a_n) bn=f(an)
具体操作:

  • b [ 1 ] = a [ 1 ] b[1]=a[1] b[1]=a[1]
  • b [ n ] = a [ n ] b[n]=a[n] b[n]=a[n]
  • 对于 1 < i < n 1<i<n 1<i<n b [ i ] b[i] b[i] a [ i − 1 ] , a [ i ] , a [ i + 1 ] a[i-1],a[i],a[i+1] a[i1],a[i],a[i+1]的中位数

定义一个序列 a n a_n an是稳定指 f ( a n ) = a n f(a_n)=a_n f(an)=an
给出一个01序列 a n a_n an
求出需要进行多少次平滑化后 a n a_n an是稳定的,并求出最后稳定的序列是什么

分析

首先思考中位数
因为 a n a_n an是01序列,那么如果当前位置 i i i a [ i − 1 ] a[i-1] a[i1]或者 a [ i + 1 ] a[i+1] a[i+1]= a [ i ] a[i] a[i],那么 i i i这个位置是不用变的
那么把序列扩大
容易发现只有像0101010……或者1010101……这样的序列才会在平滑化发生改变
那么我们只需要暴力找10交替的序列,记录一下答案

  • 当01交替序列的长度为奇数时,需要平滑化的次数是 长度整除2,最后的序列全部都是第一个数
    例如01010,最后就会变成00000
  • 当01交替序列的长度为偶数时,需要平滑化的次数是 (长度整除2)-1,最后的序列会是前一半是第一个数,后一半是最后一个数
    例如0101,最后就会变成0011

O ( n ) O(n) O(n)暴力寻找即可

Code

#include<cstdio>
#include<iostream>
using namespace std;
int n,i,j,k,num,l,ans,a[500005],c[500005];
int main()
{
	freopen("median.in","r",stdin);
	freopen("median.out","w",stdout);
	scanf("%d",&n);
	for (i=1;i<=n;i++)
		scanf("%d",&a[i]);
	i=1;
	while (i<=n)
	{
		num=1;
		j=i+1;
		while (j<=n)
		{
			if ((j-i)%2==0)
			{
				if (a[j]!=a[i]) break;
				num++;
				j++;	
			}	
			else
			{
				if (a[j]==a[i]) break;
				num++;
				j++;
			}
		}
		if (num==1) c[i]=a[i];
		if (num>1&&num%2==1)
		{
			l=num/2;
			ans=max(ans,l);
			for (k=i;k<j;k++)
				c[k]=a[i];	
		}
		if (num>1&&num%2==0)
		{
			l=num/2-1;
			ans=max(ans,l);
			for (k=i;k<=i+num/2-1;k++)
				c[k]=a[i];
			for (k=i+num/2;k<j;k++)
				c[k]=a[j-1];
		}
		i=j;
	}	
	printf("%d\n",ans);
	for (i=1;i<=n;i++)
		printf("%d ",c[i]);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值