目录
题目:
题目描述:
对于每个案例,给你一串可能 ' 0 ' ,' 1 ' ,' ? ' 的字符串,我称之为模板,' ? ' 表示可以替换成 ' 0 ' 或 ' 1 ' ,你的任务是,根据给出的模板,中找出其中一种字符串,它是所有根据模板设计出来的字符串中用最少 reverse 操作就能排成非递减序列的(形如00000111)
reverse 操作:指选取一个连续字串,进行逆转排序(如11010,变成01011)
思路:
首先一个问题,为了得到最终的非递减序列,什么会影响逆转操作次数?我们会发现,我们总是要把( 连续的 0 左边的 连续的 1 )挪到( 连续的 0 )右边,所以当数字越不连续的时候,需要的逆转次数就越多。此题没有要求求出最小逆转次数,所以推导到这里就够了。
所以我们的目的就变成了如何转变 ' ? ' 变成能让序列尽可能连续的情况
我们不妨对 ' ? ' 的出现位置以及旁边相邻的字符情况进行一个分析,举一些例子:
1?0?
0??1
1?1?
0?0
??1?
??0?
我们发现,为了尽可能让序列连续,我们只用让所有连续的'?'都跟距离最近的上一次出现的 ' 0 ' 或 ' 1 ' 相同就能达到最大程度的连续。如果是开头连续的 ' ? ' 我们只需要然他们与后面第一次出现的 ' 0 ' 或 ' 1 ' 相同就行(即1?0?→1100,??0?→0000)
特别的要注意,如果给你的是全 ' ? ' 的情况(如??????),我们只需要全给改成 0 或全改成 1 就行。
思路有了,具体操作请看AC代码
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 5;
int main()
{
std::ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
string s;
cin >> s;
memset(a, 0, sizeof(a));
//开始处理开头的连续的?
int j = 0;
char temp = s[0];//temp是第一个出现的 '0' 或 '1' 字符(初始值为 '?' )
while (j < s.size() && (s[j] == temp || s[j] == '?' || temp == '?'))
{
if (s[j] == '1')
temp = '1';
else if (s[j] == '0')
temp = '0';
j++;
}
if (temp == '?')//以应对如:"??????"的情况
temp = '1';
for (int p = 0; p < j; p++)
cout << temp;
//有了第一个出现的 '0' 或 '1' 字符
//后面只需要看上一个是什么字符就知道碰到 '?' 该输出什么字符了
for (int i = j; i < s.size(); i++)
{
if (s[i] == '?')
cout << temp;
else
{
cout << s[i];
temp = s[i];
}
}
cout << '\n';
}
return 0;
}