Codeforces Round #652 (Div. 2) #B. AccurateLee

B. AccurateLee
time limit per test2 seconds
memory limit per test256 megabytes
input:standard input
output:standard output

Lee was cleaning his house for the party when he found a messy string under the carpets. Now he’d like to make it clean accurately and in a stylish way.

The string s he found is a binary string of length n (i. e. string consists only of 0-s and 1-s).

In one move he can choose two consecutive characters s i s_i si and s i + 1 s_{i+1} si+1, and if s i s_i si is 1 and s i + 1 s_{i+1} si+1 is 0, he can erase exactly one of them (he can choose which one to erase but he can’t erase both characters simultaneously). The string shrinks after erasing.

Lee can make an arbitrary number of moves (possibly zero) and he’d like to make the string s as clean as possible. He thinks for two different strings x and y, the shorter string is cleaner, and if they are the same length, then the lexicographically smaller string is cleaner.

Now you should answer t test cases: for the i i i-th test case, print the cleanest possible string that Lee can get by doing some number of moves.

Small reminder: if we have two strings x and y of the same length then x is lexicographically smaller than y if there is a position i i i such that x 1 = y 1 , x 2 = y 2 , . . . , x i − 1 = y i − 1 a n d x i < y i x_1=y_1, x_2=y_2,..., x_{i−1}=y_{i−1} and x_i<y_i x1=y1,x2=y2,...,xi1=yi1andxi<yi.

Input

The first line contains the integer t ( 1 ≤ t ≤ 1 0 4 1≤t≤10^4 1t104) — the number of test cases.

Next 2t lines contain test cases — one per two lines.

The first line of each test case contains the integer n ( 1 ≤ n ≤ 1 0 5 1≤n≤10^5 1n105) — the length of the string s.

The second line contains the binary string s. The string s is a string of length n which consists only of zeroes and ones.

It’s guaranteed that sum of n over test cases doesn’t exceed 1 0 5 10^5 105.

Output

For each polygon, print ‘YES’ if it’s beautiful or NO otherwise (case insensitive).

Example

  • Input:
    5
    10
    0001111111
    4
    0101
    8
    11001101
    10
    1110000000
    1
    1

  • Output:
    0001111111
    001
    01
    0
    1

  该题让你将给定0-1字符串改写成最简形式(字符串长度最短,如果有多种条件使得字符串长度相同,则取字典序最小的结果。),仅有10形式的字符串可以任意去掉01。所以,我们可以观察到,最左边的0和最右边的1都是无法删去的。在此,我们可以把字符串分成三类来讨论。

  • 1、全部为 0 0 0或者 1 1 1的序列,无法删去任何一个字符,直接输出即可。
  • 2、形如 000011111 000011111 000011111的序列,左边全为 0 0 0,右边全为1,也可以直接输出。
  • 3、在字符串中既包含 0 0 0,又包含 1 1 1的序列。由于该字符串中至少包含一个 0 0 0和一个 1 1 1,故可以推出,最右边的 0 0 0左边的 1 1 1皆可消去,最左边的 1 1 1右边所有 0 0 0均可消去。我们可以将字符串 s s s拆分成三部分:
    • (1)最左边的1左边的所有0;
    • (2)最左边的1~最右边的0之间的所有字符;
    • (3)最右边的0右边的所有1;

  我们可以得到,结果字符串为第一部分和第三部分拼接而成。而中间的以1开头,0结尾的字符串都可以消去,最终可以只剩下一个0或者一个1;由于结果要按照字典序排布,故取剩下的那个0;

代码如下:

#include<iostream>
using namespace std;
void solve();
int main()
{
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}
void solve()
{
    char* s;
    int n;
    cin >> n;
    s = new char[n + 1];
    cin >> s;
    int c0 = 0, c1 = 0;
    for (int i = 0; i < n; i++)
    {
        if (s[i] == '0')c0++;
        else c1++;
    }
    if (c1 == 0 || c0 == 0) cout << s << endl;
    else {
        int postlast = 0, postfirst = -1;
        int i0 = 0;
        while (s[i0] == '0') {
            postfirst++;
            i0++;
        }
        for (int i = n - 1; i >= 0; i--)
        {
            if (s[i] == '0') {
                postlast = i;
                break;
            }
        }
        if (postfirst >= postlast) {
            cout << s << endl;
        }
        else {
            for (int i = 0; i <= postfirst; i++)
                cout << s[i];
            for (int i = postlast; i < n; i++)
                cout << s[i];
            cout << endl;
        }
    }
}

  该题思路不算复杂,但是需要注意的就是中间只要时1开头,0结尾的所有字符串都是可以消去,达到最简形式的,根据字典序排布,都可以变成0;但是不能只着眼于中间某一段,有可能你将前面消去了之后反而使后面的0无法消去,从而造成得到的字符串不是最简字符串的形式。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值