zoukankan      html  css  js  c++  java
  • 题解 CF1399D 【Binary String To Subsequences】

    题目链接:http://codeforces.com/contest/1399/problem/D
    题目描述:

    You are given a binary string s consisting of n zeros and ones.
    Your task is to divide the given string into the minimum number of subsequences in such a way that each character of the string belongs to exactly one subsequence and each subsequence looks like "010101 ..." or "101010 ..." (i.e. the subsequence should not contain two adjacent zeros or ones).
    Recall that a subsequence is a sequence that can be derived from the given sequence by deleting zero or more elements without changing the order of the remaining elements. For example, subsequences of "1011101" are "0", "1", "11111", "0111", "101", "1001", but not "000", "101010" and "11100".
    You have to answer t independent test cases.

    Input

    The first line of the input contains one integer t (1≤t≤2⋅(10^4)) — the number of test cases. Then t test cases follow.
    The first line of the test case contains one integer n (1≤n≤2⋅ (10^5)) — the length of s. The second line of the test case contains n characters '0' and '1' — the string s.
    It is guaranteed that the sum of n does not exceed 2⋅ (10^5) (∑n≤2⋅(10^5)).

    Output

    For each test case, print the answer: in the first line print one integer k (1≤k≤n) — the minimum number of subsequences you can divide the string s to. In the second line print n integers (a_1),(a_2),…,(a_n) (1≤(a_i)≤k), where (a_i) is the number of subsequence the i-th character of s belongs to.
    If there are several answers, you can print any.

    最开始的朴素做法(这种做法会TLE):
    用一个数组c来存储每个子序列最后的数字,在遍历数组a的同时使(a_i)遍历数组c,使其接上满足题意的子序列。如果没有找到,(a_i)单独作为一个子序列。用(b_i)来记录(a_i)是属于第几个子序列的,因为是保序的,只需令(b_i)=j+1就行了。

    #include<iostream>
    #include<vector>
    using namespace std;
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            char x;
            cin>>n;
            vector<int> a(n+5),b(n+5),c;
            for(int i=1;i<=n;i++)
            {
                cin>>x;
                a[i]=x-'0';
            }
            
            c.push_back(a[1]);
            b[1]=1;
            for(int i=2;i<=n;i++)
            {
                int len=c.size();
                bool flag=true;
                for(int j=0;j<len;j++)
                {
                    if(a[i]+c[j]==1)
                    {
                        c[j]=a[i];
                        b[i]=j+1;
                        flag=false;
                    }
                    if(flag==false)
                    break;
                }
                if(flag==true)
                {
                    c.push_back(a[i]);
                    b[i]=len+1;
                }
            }
            cout<<c.size()<<endl;
            //cout<<"n=="<<n<<endl;
            for(int i=1;i<=n;i++)
               cout<<b[i]<<" ";
            cout<<endl;
            c.clear();
            //cout<<"c.size()=="<<c.size()<<endl;
        }
        return 0;
    }
    

    正确做法:上面的朴素做法会TLE的根本原因在于对于每一个(a_i)都要遍历一遍数组c,这样时间复杂度就上去了,而实际上我们只需要对每个(a_i)判断当前已经存在的子序列中是否有以1结尾的子序列或以0结尾的子序列即可。而不需要每次遍历。因此我们用两个数组分别来存取以0或1结尾的子序列就可以了。这时为了确定(b_i)的值,我们需要对两个数组中所存储的值进行修改,应该存储的是每个子序列的编号,而不再是0或1了。

    #include<iostream>
    #include<vector>
    #include<string>
    using namespace std;
    string s;
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t;
        cin >> t;
        while (t--)
        {
            int n;
            cin >> n >> s;
            vector<int> b(n + 5), c0, c1;
            for (int i = 0;i < n;i++)
            {
                int newpos;
                if (s[i] == '0')
                {
                    newpos = c0.size() + c1.size();
                    if (c1.empty())
                    {
                        c0.push_back(newpos);
                    }
                    else
                    {
                        newpos = c1.back();
                        c1.pop_back();
                        c0.push_back(newpos);
                    }
                }
                else
                {
                    newpos = c0.size() + c1.size();
                    if (c0.empty())
                    {
                        c1.push_back(newpos);
                    }
                    else
                    {
                        newpos = c0.back();
                        c0.pop_back();
                        c1.push_back(newpos);
                    }
                }
                b[i] = newpos + 1;
            }
            cout << c0.size() + c1.size() << endl;
            for (int i = 0;i < n;i++)
                cout << b[i] << " ";
            cout << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    OC_框架学习第一天
    OC_协议与分类的学习
    OC内存分析之retain与copy的简单测试示例
    OC类的使用,属性声明与复合类的实现示例
    PL/SQL破解方法(不需要注册码)
    C# Winform应用程序占用内存较大解决方法整理
    分享一个控制台版本《推箱子》小游戏,感兴趣的可以看看
    每天定时去女友空间留言工具(首选你要有个女友。!哈哈哈哈)
    单例模式(Singleton)详解——转载
    easyUI的datagrid控件日期列不能正确显示Json格式数据的解决方案
  • 原文地址:https://www.cnblogs.com/Acapplella/p/13452829.html
Copyright © 2011-2022 走看看