codeforces D. Subsequence Hate - 前缀和枚举

codeforces D. Subsequence Hate - 前缀和枚举

题干

Shubham has a binary string s. A binary string is a string containing only characters “0” and “1”.

He can perform the following operation on the string any amount of times:

Select an index of the string, and flip the character at that index. This means, if the character was “0”, it becomes “1”, and vice versa.
A string is called good if it does not contain “010” or “101” as a subsequence — for instance, “1001” contains “101” as a subsequence, hence it is not a good string, while “1000” doesn’t contain neither “010” nor “101” as subsequences, so it is a good string.

What is the minimum number of operations he will have to perform, so that the string becomes good? It can be shown that with these operations we can make any string good.

A string a is a subsequence of a string b if a can be obtained from b by deletion of several (possibly, zero or all) characters.

Input
The first line of the input contains a single integer t (1≤t≤100) — the number of test cases.

Each of the next t lines contains a binary string s (1≤|s|≤1000).

Output
For every string, output the minimum number of operations required to make it good.

Example

input

7
001
100
101
010
0
1
001100

output
0
0
1
1
0
0
2

Note
In test cases 1, 2, 5, 6 no operations are required since they are already good strings.

For the 3rd test case: “001” can be achieved by flipping the first character — and is one of the possible ways to get a good string.

For the 4th test case: “000” can be achieved by flipping the second character — and is one of the possible ways to get a good string.

For the 7th test case: “000000” can be achieved by flipping the third and fourth characters — and is one of the possible ways to get a good string.

二进制字符串s,若干次操作:
翻转一个字符
好串为不存在序列为010或101的串(即所有的1和0都是连续出现的)
最少操作几次使s成为好串

知识点&算法

不能出现任何01交替的序列,意思就是所有01都是凑在一起出现的,0000011111,111110000这样子。
如果要翻转,我们枚举一个中点,中点及左侧全部置0/1,中点右侧全部置1/0。对于枚举的每个点取两种情况中更小的次数。
为了降低时间复杂度,我们用两个前缀和数组cnt0[i]和cnt1[i]来存储串前i位出现的0,1个数:
设串长为n,那么对于每个中点i来说,翻转的代价即为cnt0[i] + cnt1[n] - cnt1[i](左置1右置0)和cnt1[i] + cnt0[n] - cnt0[i](左置1右置0)

题解

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
string s;
int __,n,x,y,z,a,b,c,u,v,res;
int cnt0[1005],cnt1[1005];

int main()
{
    cin>>__;
    while(__--){
        cin>>s;
        n = s.length();
        res = 0x3f3f3f3f;
        memset(cnt0,0,sizeof(cnt0));
        memset(cnt1,0,sizeof(cnt1));
        cnt0[1] = s[0] == '0';
        cnt1[1] = s[0] == '1';
        for(int i = 2 ; i <= n ; ++i){
            cnt0[i] = cnt0[i-1] + (s[i-1] == '0');
            cnt1[i] = cnt1[i-1] + (s[i-1] == '1');
        }
        for(int i = 0 ; i <= n ; ++i){
            res = min(res,min(cnt0[i]+cnt1[n]-cnt1[i],cnt1[i]+cnt0[n]-cnt0[i]) );
        }
        cout<<res<<endl;
    }
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CodeForces - 616D是一个关于找到一个序列中最长的第k好子段的起始位置和结束位置的问题。给定一个长度为n的序列和一个整数k,需要找到一个子段,该子段中不超过k个不同的数字。题目要求输出这个序列最长的第k好子段的起始位置和终止位置。 解决这个问题的方法有两种。第一种方法是使用尺取算法,通过维护一个滑动窗口来记录\[l,r\]中不同数的个数。每次如果这个数小于k,就将r向右移动一位;如果已经大于k,则将l向右移动一位,直到个数不大于k。每次更新完r之后,判断r-l+1是否比已有答案更优来更新答案。这种方法的时间复杂度为O(n)。 第二种方法是使用枚举r和双指针的方法。通过维护一个最小的l,满足\[l,r\]最多只有k种数。使用一个map来判断数的种类。遍历序列,如果当前数字在map中不存在,则将种类数sum加一;如果sum大于k,则将l向右移动一位,直到sum不大于k。每次更新完r之后,判断i-l+1是否大于等于y-x+1来更新答案。这种方法的时间复杂度为O(n)。 以上是两种解决CodeForces - 616D问题的方法。具体的代码实现可以参考引用\[1\]和引用\[2\]中的代码。 #### 引用[.reference_title] - *1* [CodeForces 616 D. Longest k-Good Segment(尺取)](https://blog.csdn.net/V5ZSQ/article/details/50750827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces616 D. Longest k-Good Segment(双指针+map)](https://blog.csdn.net/weixin_44178736/article/details/114328999)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值