• 【33.10%】【codeforces 604C】Alternative Thinking


    time limit per test2 seconds
    memory limit per test256 megabytes
    inputstandard input
    outputstandard output
    Kevin has just recevied his disappointing results on the USA Identification of Cows Olympiad (USAICO) in the form of a binary string of length n. Each character of Kevin’s string represents Kevin’s score on one of the n questions of the olympiad—’1’ for a correctly identified cow and ‘0’ otherwise.

    However, all is not lost. Kevin is a big proponent of alternative thinking and believes that his score, instead of being the sum of his points, should be the length of the longest alternating subsequence of his string. Here, we define an alternating subsequence of a string as a not-necessarily contiguous subsequence where no two consecutive elements are equal. For example, {0, 1, 0, 1}, {1, 0, 1}, and {1, 0, 1, 0} are alternating sequences, while {1, 0, 0} and {0, 1, 0, 1, 1} are not.

    Kevin, being the sneaky little puffball that he is, is willing to hack into the USAICO databases to improve his score. In order to be subtle, he decides that he will flip exactly one substring—that is, take a contiguous non-empty substring of his score and change all ‘0’s in that substring to ‘1’s and vice versa. After such an operation, Kevin wants to know the length of the longest possible alternating subsequence that his string could have.

    Input
    The first line contains the number of questions on the olympiad n (1 ≤ n ≤ 100 000).

    The following line contains a binary string of length n representing Kevin’s results on the USAICO.

    Output
    Output a single integer, the length of the longest possible alternating subsequence that Kevin can create in his string after flipping a single substring.

    Examples
    input
    8
    10000011
    【题目链接】:http://codeforces.com/contest/604/problem/C

    【题解】

    先把连续的0串和1串压缩成一位.
    这样整个字符串就是符合要求的01间隔出现的串了.记录每一位压缩了几个。
    这个串的长度就是初始的间隔01串的长度.
    接下来.
    考虑以下几种情况.
    1.
    某一位压缩的个数>=3;
    则可以在中间位置进行取反操作(一个数就可以);
    这样就把01串的长度增加了2;(而2是一次操作能够增加的最多位数);
    所以直接输出就可以了.
    2.有连续两位,这两位的压缩位数分别都是2;

    1100这样的情况
    可以变成1010
    也是增加2;
    所以这种情况也直接输出答案.
    3.有两位,这两位压缩数都是2,且它们中间间隔的位,压缩位数都是1。

    1101011
    这种情况2..len-1取反
    1010101
    可以发现也能增加2;
    所以也可以直接输出
    4.有一位它的压缩位数为2.则答案增加1
    5.全都是1位。答案和原来一样(不会减少的,可以全都取反啊。。这个时候全是1为了哦);

    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%I64d",&x)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int MAXN = 1e5+100;
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    
    char s[MAXN];
    vector <pii> a;
    int n;
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        rei(n);
        scanf("%s",s+1);
        int i = 1;
        bool judge1 = false,judge2 = false;
        while (i <= n)
        {
            int j = i+1;
            while (j <=n && s[j] == s[i]) j++;
            a.pb(mp(s[i]-'0',j-i));
            if (j-i>=3)
                judge1 = true;
            i = j;
        }
        int ans1 = a.size();
        if (judge1)
        {
            cout << ans1+2 << endl;
            return 0;
        }
        rep1(i,0,ans1-1)
        {
            if (i+1<=ans1-1)
            {
                int ma = max(a[i].se,a[i+1].se),mi = min(a[i].se,a[i+1].se);
                if (ma ==2 && mi ==2)
                {
                    cout << ans1+2<<endl;
                    return 0;
                }
                else
                    if (ma==2)
                        judge2 = true;
            }
        }
        if (ans1==1 && a[0].se==2)
            judge2 = true;
        rep1(i,0,ans1-1)
            if (a[i].se==2 && i+1<=ans1-1)
            {
                int j = i+1;
                while (j <= ans1-1 && a[j].se==1) j++;
                if (a[j].se == 2)
                {
                    cout << ans1+2<<endl;
                    return 0;
                }
                else
                    judge2 = true;
            }
        if (judge2)
            cout << ans1+1<<endl;
        else
            cout << ans1<<endl;
        return 0;
    }
  • 相关阅读:
    jQuery之父:每天都写点代码
    XtraTabControl 控件使用
    Linq:使用Take和Skip实现分页
    WCF教程一之WCF是什么,能做什么
    WCF发布后远程访问的域名解析问题
    C# WinForm下,隐藏主窗体,只在进程管理器中显示进程,在任务栏,状态栏都不显示窗体的方法
    在bat脚本写入中文远行后乱码
    VS2010DebugView捕捉
    Web Service 的工作原理
    String.Format 方法
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626810.html
Copyright © 2020-2023  润新知