Code Foces Div.2——C. Binary String

今天说一道很让我蛋疼的一道水题——那就是Div.2——C. Binary String。

偷偷打个哈欠

话不多说, 上链接:

Problem - C - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1680/problem/C

You are given a string ss consisting of characters 0 and/or 1.

You have to remove several (possibly zero) characters from the beginning of the string, and then several (possibly zero) characters from the end of the string. The string may become empty after the removals. The cost of the removal is the maximum of the following two values:

  • the number of characters 0 left in the string;
  • the number of characters 1 removed from the string.

What is the minimum cost of removal you can achieve?

Input

The first line contains one integer tt (1≤t≤1041≤t≤104) — the number of test cases.

Each test case consists of one line containing the string ss (1≤|s|≤2⋅1051≤|s|≤2⋅105), consisting of characters 0 and/or 1.

The total length of strings ss in all test cases does not exceed 2⋅1052⋅105.

Output

For each test case, print one integer — the minimum cost of removal you can achieve.

Example

input

Copy

5
101110110
1001001001001
0000111111
00000
1111

output

Copy

1
3
0
0
0

Note

Consider the test cases of the example:

  1. in the first test case, it's possible to remove two characters from the beginning and one character from the end. Only one 1 is deleted, only one 0 remains, so the cost is 11;
  2. in the second test case, it's possible to remove three characters from the beginning and six characters from the end. Two characters 0 remain, three characters 1 are deleted, so the cost is 33;
  3. in the third test case, it's optimal to remove four characters from the beginning;
  4. in the fourth test case, it's optimal to remove the whole string;
  5. in the fifth test case, it's optimal to leave the string as it is.

       题意是给定一个 01 串,从开头和结尾各删去一些数(可以不删),求 删除的 1 的个数 与 剩下的 0 的个数 的最大值。

       乍一看虽然没有头绪, 但是仔细一想,既然我要找的是01串中删1数和剩0数中的大值

那当我们取得最优解时删去的1的个数应该和剩下的0的个数相等,也就是删1数 = 剩0数

我们还能知道删去的数字个数 = 删1数 + 删0数;

       易得取最优解时删去的数字个数 = 删0数 + 剩0数;也就是原串中有几个0, 变成最优解就要删去几个数字。

       为了保险起见, 我们可以用样例进行验证

101110110  ——>  3颗0 ——> 111011——>删1个1, 剩1个0

1001001001001 ——>8颗0 ——> 10010删3个1, 剩3个0

0000111111 ——>4颗0——>111111——>删0个1, 不剩0

00000 ——>空串——>不删1不剩0

1111 ——>1111——>不删1不剩0

       经过上面的验证, 我们可以得出我们的推断是正确的

虽然结论正确, 可能有些人还没有理解这个推论有什么用。

       不要急, 我们接着看

我们不妨把原串中0的个数记为num0。

既然我们变成最优解要删除num0个数字, 而且只能从前和后两边删除。

现在是不是豁然开朗了。

只要从前后两端分别取数, 总数为num0, 找最少包含几个1就可以结束了。

都这个时候了那就上代码吧

#include<iostream>
#include<cstring>
 
using namespace std;
 
int T, n;
char a[20010];
 
int main()
{
	scanf("%d", &T);
	while(T -- )
	{
		int num0 = 0, num1 = 0;
		scanf("%s", &a);
		n = strlen(a);
		for(int i = 0; i < n; i ++ ) if(a[i] == '0') num0 ++;
		int ans = 100000;
		for(int i = 0; i < num0; i ++ )
		{
			int s1 = 0;
			for(int j = 0; j < num0 - i - 1; j ++ ) if(a[j] == '1') s1 ++;
			for(int j = n - i - 1; j < n; j ++ ) if(a[j] == '1') s1 ++;
			ans = min(ans, s1);
		}
		if(num0 != 0)printf("%d\n", ans);
		else printf("0\n");
	}
	
	return 0;
}

但是, 真的就这样结束了么?

细心的大佬们可能发现了(tnnd, 为什么我当时就没发现, 甚至还暴力写出来了, 甚至还疯狂DEBUG!!!!!!

虽然思路非常的简单, 但是如果这时我用暴力的话, 就一定会超时, 而且这难以把握的边界, DEBUG对我这种手残&脑残党来说非常非常的残忍。

大家千万不要学我, 都是血的教训啊。

 除此之外还在VJ上错了两次。

好,吐槽完自己就继续说明吧, 应该有很多大佬会有自己的想法, 不就是二分么, 不就是。。。么, 但是, 我要讲一个更加简单的方法,毕竟像我这样的小白有可能连二分都不会用, 话不多说, 上代码。

#include<iostream>
#include<cstring>
 
using namespace std;
 
const int N = 2e5 + 10;
int T, n;
char a[N], b[N];
 
int main()
{
	scanf("%d", &T);
	while(T -- )
	{
		int num0 = 0;
		scanf("%s", &a);
		n = strlen(a);
		for(int i = 0; i < n; i ++ ) if(a[i] == '0') num0 ++;
		for(int i = 0, j = n - 1; i < n; i ++, j -- ) b[i] = a[j];
		int ans, s1 = 0;
		for(int i = 0; i < num0; i ++ ) if(a[i] == '1') s1 ++;
		ans = s1;
		for(int i = 0; i < num0; i ++ )
		{
			s1 = s1 + (int)a[n - i - 1];
			s1 = s1 - (int)a[num0 - i - 1];
			ans = min(s1, ans);
		}
		printf("%d\n", ans);
	}
	
	return 0;
}

因为代码并不难, 所以我就没有注释, 也希望大家不要重蹈我一道题错18次的覆辙。

祝大佬们天天AK!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值