ACM学习历程—CodeForces 590A Median Smoothing(分类讨论 && 数学)

题目链接:http://codeforces.com/problemset/problem/590/A

题目大意是给一个串,头和尾每次变换保持不变。

中间的a[i]变成a[i-1],a[i],a[i+1]的中位数,而且此题串是01串。

对于01

0 0 0中位数是0

0 0 1中位数是0

0 1 1中位数是1

1 1 1中位数是1

所以

1、串中有两个相邻以上的0或者1是保持不变的。

2、会变的只有是两个1中间的0或者两个0中间的1

但是到这里的话,虽然证明了肯定能变成稳定态,就算把相同数字分组模拟,给1010101010.....这种形式的话需要O(n)次才能稳定。自然不能模拟。。

由于条件2,发现如果两个满足1的串中间夹着0101这种间隔的串,那么这一段只有中间0101串会变化。

那么我只需要输入时分组,对于每两个满足1的串处理中间的0101串,然后取所有0101串变换的最大次数即为答案所要求。

然后考虑两个满足1的串:

两头是0或者两头是1是同一种情况:

1110101010111 ->变换4次得到1111111111111

一头是0一头是1

111010101000->变换3次得到111111000000

然后就发现就是变换(中间串长度+1/2次,得到的全10,或者一半1一半0

然后写的时候要特殊考虑一下一开始全01,或者一半0一半1发情况。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#define LL long long

using namespace std;

const int maxN = 500005;
int n, top;
struct node
{
    bool val;
    int num;
}s[3][maxN];

void input()
{
    top = -1;
    int u;
    for (int i = 0; i < n; ++i)
    {
        scanf("%d", &u);
        if (top == -1 || u != s[0][top].val)
        {
            top++;
            s[0][top].val = u;
            s[0][top].num = 1;
        }
        else s[0][top].num++;
    }
}

void work()
{
    int run = 0, ttop = -1, from, cnt;
    for (int i = 0; i <= top; i++)
    {
        ttop++;
        s[1][ttop] = s[0][i];
        if (i < top-1 && s[0][i+1].num == 1)
        {
            from = i;
            i++;
            while (s[0][i].num == 1 && i < top) i++;
            if (s[0][from].val == s[0][i].val)
            {
                cnt = i-from+1;
                ttop++;
                s[1][ttop].val = s[0][i].val;
                s[1][ttop].num = cnt-2;
                run = max(run, cnt/2);
            }
            else
            {
                cnt = i-from+1;
                ttop++;
                s[1][ttop].val = s[0][from].val;
                s[1][ttop].num = cnt/2-1;
                ttop++;
                s[1][ttop].val = s[0][i].val;
                s[1][ttop].num = cnt/2-1;
                run = max(run, cnt/2-1);
            }
            i--;
        }
    }
    printf("%d\n", run);
    bool flag = false;
    for (int i = 0; i <= top; ++i)
    {
        for (int j = 0; j < s[1][i].num; ++j)
        {
            if (flag) printf(" ");
            printf("%d", s[1][i].val);
            flag = true;
        }
    }
    printf("\n");
}

int main()
{
    //freopen("test.in", "r", stdin);
    while (scanf("%d", &n) != EOF)
    {
        input();
        work();
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/andyqsmart/p/5028642.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值