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;
}
全剧终