CF1889A Qingshan Loves Strings 2

Luogu 链接
CodeForces 链接
Virtual Judge 链接

题意

我们称长度为 \(k\)\(\texttt{01}\)\(a\)好的当且仅当

  • \(\forall\ i\in\left[1,k\right],a_i\neq 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\) 组样例,模拟的情况如下:

  • \(s=\texttt{001110}\)\(i=1\)\(j=6\)\(s_i=s_j=0\),在 \(s_j\) 后插入 \(\texttt{01}\)

  • \(s=\texttt{00111001}\)\(i=2\)\(j=7\)\(s_i=s_j=0\),在 \(s_j\) 后插入 \(\texttt{01}\)

  • \(s=\texttt{0011100011}\)\(i=3\)\(j=8\)\(s_i\ne s_j\),跳过。

  • \(s=\texttt{0011100011}\)\(i=4\)\(j=7\)\(s_i\ne s_j\),跳过。

  • \(s=\texttt{0011100011}\)\(i=5\)\(j=6\)\(s_i\ne s_j\),结束。

因此输出结果为:

2
6 7

程序

AC 记录

#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);//输出ans
	for(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;
}
posted @ 2025-03-09 08:41  LXcjh4998  阅读(30)  评论(0)    收藏  举报