题目链接
题意
我们称长度为 $k$ 的 $\texttt{01}$ 串 $a$ 是好的当且仅当
- $\forall i\in\left[1,k\right],a_i\ne a_{k-i+1}$
现在给你 $t$ 个 $\texttt{01}$ 串 $s$,你可以执行不多于 $300$ 次以下操作使得 $s$ 变为好的(次数可以为 $0$):
- $\text{插入}\texttt{01}\text{到}s\text{的任意位置}$
对于每个 $\texttt{01}$ 串 $s$,若无法使它变好,则输出 $-1$;否则输出操作次数和每次插入的位置 $x_i$(当 $x_i=0$ 时表示插入到 $s$ 的开头,否则表示插入到 $s_i$ 的后面)。
思路
首先,一个 $\texttt{01}$ 串 $s$ 如果是好的,则它的 $0$ 和 $1$ 的个数应该相等(这是因为 $s_i$ 和 $s_{k-i+1}$ 中必须一个是 $0$,一个是 $1$)。
又因为插入 $\texttt{01}$ 不能使 $s$ 中 $0$ 和 $1$ 的个数由不相等变为相等。
因此我们可以统计 $s$ 中 $0$ 和 $1$ 的个数,若不相等则直接输出 $-1$,否则要继续寻找方案。
我们可以使用双指针 $i$ 和 $j$ 遍历字符串 $s$:
- 当 $s_i=s_j=0$ 时,我们可以将 $\texttt{01}$ 插入到 $s_j$ 的后面。
- 当 $s_i=s_j=1$ 时,我们可以将 $\texttt{01}$ 插入到 $s_i$ 的前面。
- 当 $s_i\ne s_j$ 时,则不做处理。
用一个变量记录插入的次数,用一个数组记录插入的位置,最后输出即可。
例如,对于第 $4$ 组样例,模拟的情况如下(字符串中标红的为 $i$ 和 $j$ 的位置):
-
$s=\texttt{\textcolor{red}{0}0111\textcolor{red}{0}}$,$i=1$,$j=6$,$s_i=s_j=0$,在 $s_j$ 后插入 $\texttt{01}$。
-
$s=\texttt{0\textcolor{red}{0}1110\textcolor{red}{0}1}$,$i=2$,$j=7$,$s_i=s_j=0$,在 $s_j$ 后插入 $\texttt{01}$。
-
$s=\texttt{00\textcolor{red}{1}1100\textcolor{red}{0}11}$,$i=3$,$j=8$,$s_i\ne s_j$,跳过。
-
$s=\texttt{001\textcolor{red}{1}10\textcolor{red}{0}011}$,$i=4$,$j=7$,$s_i\ne s_j$,跳过。
-
$s=\texttt{0011\textcolor{red}{1}\textcolor{red}{0}0011}$,$i=5$,$j=6$,$s_i\ne s_j$,结束。
因此输出结果为:
2
6 7
程序
#include<bits/stdc++.h>
using namespace std;
int t,len,sum0,sum1,ans,arr[300];//t为组数,len为字符串的长度,sum0、sum1分别为字符串中0、1的个数,ans为操作次数,arr[]存储插入的位置
char str[702];//str[]存储字符串
void solve(){sum0=sum1=ans=0;//初始化 scanf("%d%s",&len,str+1);//读入len和str[] for(int i=1;i<=len;++i){//统计0和1的个数 if(str[i]=='0')++sum0;else ++sum1;}if(sum0!=sum1){//如果不相等,输出-1并返回 printf("-1\n");return;}for(int i=1,j=len;i<j;){if(str[i]=='0'&&str[j]=='0'){ arr[ans++]=j;//记录插入位置 for(int k=len+1,l=len+3;k>j;--k,--l)str[l]=str[k];//在str[j]后插入01 str[j+1]='0',str[j+2]='1';len+=2,++i,++j;//增加长度,移动指针 }else if(str[i]=='1'&&str[j]=='1'){arr[ans++]=i-1;//记录插入位置 for(int k=len+1,l=len+3;k>=i;--k,--l)str[l]=str[k];//在str[i]前插入01,就是在str[i-1]后插入01 str[i]='0',str[i+1]='1';len+=2,++i,++j;//增加长度,移动指针 }else ++i,--j;//移动指针 }printf("%d\n",ans);//输出ansfor(int i=0;i<ans;++i)printf("%d ",arr[i]);//输出arr[] printf("\n");
}
int main(){scanf("%d",&t);//输入组数for(int i=0;i<t;++i)solve();//解决问题 return 0;
}