Loading

CF 1743D. Problem with Random Tests(贪心)

D. Problem with Random Tests(贪心)

题意

​ 给出一个01串s,请你任意选择两个子串s1, s2,输出将他们向右对齐按位与的最大值的二进制表示。

思路

​ 首先我们要知道,二进制表示最大,一定是长度越长越好,所以s1一定是选择整个串的。那么我们现在就需要思考s2要从哪里找。因为是向右对齐,所以原串s如果有前导0就没办法变1,所以我们要去除一下前导0。我们可以显而易见地想到,s1(去前导0后)中的第一个0是一定要变成1的,又因为是按右对齐的,所以我们只能从这个0左边的1选择s2的头。这样讲可能很抽象,我们举一个例子。

\(1110011101\)是s1,那么想要把\(s1_4\)变成1,我们的\(s2\)的开头就只能在前3个1里面选,然后\(s2\)越长越好。因为题目说数据均随机生成,我们在遇到第一个0之前一直暴力匹配后取最大值即可(后面已经不可能满足让第一个0变1的可能性了)。

实现

void solve()
{
	cin >> n >> s;
    string res = s;
    int st;
    //去前导0
    for(int i = 0; i < n; i ++)
        if(s[i] == '1')
        {
            st = i;
            break;
        }
    
    for(int i = st; i < n; i ++)
    {
        string tmp = s;
        for(int k = st, j = i; k < n && j < n; k ++, j ++)
            tmp[j] = max(s[k], s[j]);
        res = max(res, tmp);
        if(s[i] == '0') //因为贪心,所以第一个0一定是跟他前面的1配对的。
            break;
    }
    //去前导0
    reverse(all(res)); 
    while(res.size() > 1 && res.back() == '0')  res.pop_back();
    reverse(all(res));
    cout << res << '\n';
}
posted @ 2022-10-18 10:46  DM11  阅读(211)  评论(0编辑  收藏  举报