CF-1296E——String Coloring(DP+二分)

总结

问题:构造一个最小颜色数量的字符串

子问题:构造一个只有两种颜色的字符串

情况1:只需要一种颜色字符串就满足
说明这个字符串本身就是一个非严格递增字符串,字符串全为0

情况2:只需要两种颜色字符串就满足
说明就是两种颜色的字符串本身就是一个非严格递增的字符串,这样做交换,只是每次交换都是最优的。
举例:
s1=abcd
s2=acd;
两个字符串合并
s2的第一个字符,其实也可以一步的
abcd-acd
abcad-cd
abacd-cd
aabcd-cd

s2的第二个字符
aabcdc-d
aabccd-d

s3的第三个字符
aabccdd



情况3:大于两种的,为了构造最长的两种颜色,我们肯定两个最长非严格递增序列,如果还达不到n,就输出no

构造最小颜色数量字符串
ans=0;
先构造一个最长非严格递减序列,ans++;
再在剩下的序列构造一个最长的非严格递减序列,ans++;
直到构造完

DP
这里为啥dp开26就可以了,max(ans)=26,为什么?
每种字母取一种颜色,就是26种颜色,ans最大是26,题目要求min,

const int N=2e5+5;
int dp[26];
signed main()
{
    IOS;
    //file();
    int n,num=0;
    string str;
    vector<int>ans;
    cin>>n>>str;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<26;j++)
        {
            if(dp[j]<=str[i])
            {
                dp[j]=str[i];
                ans.pb(j+1);
                num=max(num,j+1);
                break;
            }
        }
    }
    cout<<num<<endl;
    for(auto it:ans)
        cout<<it<<" ";
    cout<<endl;
    return 0;
}

二分
由于二分函数,只能求单调非严格递增数组,所以我们求最长非严格递增序列,倒着求最长非严格递减序列,二维就是的X轴就是一个最长非严格递减序列,但是Y轴就是一个最长非严格递增序列,方便调用内部函数,当然可以自己手打,不用这么麻烦

signed main()
{
    IOS;
    //file();
    int n,num=0;
    string str;
    vector<int>ans,vec;
    cin>>n>>str;
    reverse(all(str));
    for(int i=0;i<n;i++)
    {
        int pos=lower_bound(all(vec),str[i])-vec.begin();
        ans.pb(pos+1);
        num=max(num,pos+1);
        if(pos<vec.size())
            vec[pos]=str[i];
        else
            vec.pb(str[i]);
    }
    cout<<num<<endl;
    reverse(all(ans));
    for(auto it:ans)
        cout<<it<<" ";
    cout<<endl;
    return 0;
}
发布了130 篇原创文章 · 获赞 5 · 访问量 4996

猜你喜欢

转载自blog.csdn.net/weixin_44224825/article/details/104189536
今日推荐