Median Smoothing
分类:思维、构造
1.题意概述
给你一个长度为n的01串a[1…n],进行多轮变换,每轮操作:
- b[1]=a[1],b[n]=a[n]
- 位于2…n-1的数 b[i] 为 a[i−1],a[i],a[i+1] 从大到小排列的中位数
现在问你进行多少轮变换后b数组不再发生变化,且求它的最终状态。
2.解题思路
尝试多写出一个来,发现规律:
- …010…-> …000…
- …1101011…->…1110111…->…1111111…
- …01010…->…00100…->…00000…
- …01010…->…00100…->…00000…
- …1101010…->..1110100…->…1111000
最终趋向总是一堆0一堆1,而会改变的,都是那些01间杂的序列,最终次数肯定是最大的间隔数,我们统计一下容易发现:
- 当间隔长度为奇数时候,结果总是一堆0或者一堆1!
- 当间隔长度为偶数时候,结果总是一半0一半1!
3.AC代码
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 500010
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r - t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
int a[maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long _begin_time = clock();
#endif
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
a[n + 1] = a[n];
int cnt = 1, ans = 0, l = 1, r = 1;
for (int i = 2; i <= n + 1; i++)
{
if (a[i] != a[i - 1])
{
r = i;
cnt++;
}
else
{
ans = max(ans, (cnt - 1) / 2);
if (cnt & 1)
{
for (int j = l; j <= r; j++)
a[j] = a[l];
}
else
{
int mid = l + r >> 1;
for (int j = l; j <= r; j++)
a[j] = j <= mid ? a[l] : a[r];
}
cnt = 1;
l = r = i;
}
}
printf("%d\n", ans);
for (int i = 1; i <= n; i++)
if (i == 1)
printf("%d", a[i]);
else
printf(" %d", a[i]);
puts("");
#ifndef ONLINE_JUDGE
long _end_time = clock();
printf("time = %ld ms.", _end_time - _begin_time);
#endif
return 0;
}