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;
    }
    
  • 相关阅读:
    Oracle 各种查询语句
    Win7下Eclipse中文字体太小
    ASP.NET MVC(Razor)上运用UEditor和xhEditor编辑器检测到有潜在危险的 Request.Form的真正解决办法
    Oracle 分页
    限制IIS访问流量提升IIS性能
    pl\sql工具导出表结构、序列和触发器方法
    JS 中面向对象的5种写法
    去除Windows 2003的登录CTRL+ALT+DEL
    List绑定时无法进行增删查改的解决办法
    .net工具
  • 原文地址:https://www.cnblogs.com/Acapplella/p/13452829.html
Copyright © 2011-2022 走看看