Codeforces Round #646 (Div. 2) 1和0不能互夹心的问题,和北大美团杯xxxxlllll有点像

本文详细解析了Codeforces比赛中的1363B题Subsequence Hate,介绍了官方给出的C++解题思路及代码实现,对比了不同解法的复杂度,帮助读者理解高效解题技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

B. Subsequence Hate
https://codeforces.ml/contest/1363/problem/B
上面一行是题目链接添加链接描述
下面是cf官方给的题解c++
1363B - Subsequence Hate
Key Idea: There are two types of good strings: Those which start with a series of 1’s followed by 0’s (such as 1111100) and those which start with a series of 0’s followed by 1’s (such as 00111). Note that there are strings which do belong to both categories (such as 000).

Detailed Explanation: We will use the key idea to compute the minimum change required to achieve every possible string of each of the two types, and then take the minimum across them.

First, let us compute the total number of 1’s and 0’s in the string, denoted by num_ones and num_zeros. Now, as we iterate through the string, let us also maintain done_ones and done_zeros, which denote the number of 1’s and 0’s encountered so far.

Let us iterate through the string. When we are at position i (indexed from 1), we want to answer two questions: what is the cost for changing the string into 11…000 (where number of 1’s = i) and what is the cost for changing the string into 00…111 (where number of 0’s = i).

Assuming that done_zeros and done_ones also consider the current index, the answer to the first question is done_zeros + num_ones - done_ones. This is because done_zeros 0’s must be converted to 1’s, and num_ones - done_ones 1’s must be converted to 0’s. Similarly, the answer for the second question is done_ones + num_zeros - done_zeros.

The answer is the minimum over all such changes possible. Please do not forget to consider the all 1’s and all 0’s string in the above solution.

Time Complexity: O(N)
Author of this problem was Ashishgup.

Relevant Meme
Code for B
官方写的c++;

在这里插入代码片
#include <bits/stdc++.h>
using namespace std;
 
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl "\n"
#define int long long
 
const int N = 1e5 + 5;
 
int32_t main()
{
	IOS;
	int t;
	cin >> t;
	while(t--)
	{
		string s;
		cin >> s;
		int suf0 = 0, suf1 = 0;
		for(auto &it:s)
		{
			suf0 += (it == '0');
			suf1 += (it == '1');
		}
		int ans = min(suf0, suf1); //Make whole string 0/1
		int pref0 = 0, pref1 = 0;
		for(auto &it:s)
		{
			pref0 += (it == '0'), suf0 -= (it == '0');
			pref1 += (it == '1'), suf1 -= (it == '1');
			//Cost of making string 0*1*
			ans = min(ans, pref1 + suf0);
			//Cost of making string 1*0*
			ans = min(ans, pref0 + suf1);
		}
		cout << ans << endl;
	}
	return 0;
}

我用c++仅仅只是用到的东西就学一点所以有的看不懂,也不拍丢人。
但是这个代码嘛。我不了解c++所以我比这它写成c的啦。嘻嘻
下面是我的c型copy:code

在这里插入代码片
这里面为啦省事也用啦人家的min函数比较简洁漂亮
#include <iostream>

using namespace std;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char s[1005];
int main()
{
    int t,i,ans,len;
    scanf("%d",&t);
    getchar();
    while(t--)
    {
        int suf0=0, suf1=0;
        scanf("%s",s);
        len=strlen(s);
        for(i=0;i<len;i++)
        {
            if(s[i]=='0')
                suf0++;
            else
                suf1++;
        }
        ans=min(suf0,suf1);
        int pref0=0,pref1=0;
        for(i=0;i<len;i++)
        {
            if(s[i]=='0')
            {
                pref0++,suf0--;
            }
            else
            {
                pref1++,suf1--;
            }
            ans=min(ans,pref1+suf0);
            ans=min(ans,pref0+suf1);
        }
        printf("%d\n",ans);
    }
    return 0;
}

下面就是我该说说我之前怎么做这种题啦。
数组存每个节点的特征值。特别麻烦。上次美团杯的时候就是折磨做的,麻烦死啦,人家发的题解也看不懂:没有理解当然也记不住,更不会把它记下来。这次也是。还好今天早上宇哥问我这个题解怎么看。硬着头皮看一下还真的可以。原理还是差不多的。人家的简单无论是memory还是time都非常小,俺的就是头老母猪。

在这里插入代码片
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char s[1005];
int a[1005];
int b[1005];
int c[1005];
int d[1005];
int main()
{
    int n,m,i,j,t;
    scanf("%d",&t);
    getchar();
    while(t--)
    {
        scanf("%s",s+1);
        n=strlen(s+1);
        a[0]=b[0]=c[0]=d[0]=a[n+1]=0;
        b[n+1]=c[n+1]=d[n+1]=0;
        for(i=1;i<=n;i++)
        {
            if(s[i]=='0')
            {
                a[i]=a[i-1]+1;
                b[i]=b[i-1];
            }
            else
            {
                a[i]=a[i-1];
                b[i]=1+b[i-1];
            }
        }
        for(i=n;i>=1;i--)
        {
            if(s[i]=='0')
            {
                c[i]=c[i+1]+0;
                d[i]=d[i+1]+1;
            }
            else
            {
                c[i]=c[i+1]+1;
                d[i]=d[i+1];
            }
        }
        int minm=100000;
        for(i=0;i<=n;i++)
        {
            if(a[i]+c[i+1]<minm)
                minm=a[i]+c[i+1];
            if(a[i]+d[i+1]<minm)
                minm=a[i]+d[i+1];
            if(b[i]+c[i+1]<minm)
                minm=b[i]+c[i+1];
            if(minm>b[i]+d[i+1])
                minm=b[i]+d[i+1];
        }
        printf("%d\n",minm);
    }
    return 0;
}

全剧终

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值