Codeforces Round #712 (Div. 2) A-E题

本文介绍了四道算法竞赛题目及其解决方案。A题要求在字符串中插入字符使其非回文;B题询问如何通过特定操作使两个01字符串相等;C题涉及构建特定的括号序列;D题为交互式染色问题,要求相邻颜色不同;E题求解旅行商问题的最短路径。代码实现详尽,涵盖了字符串处理、位操作、图论等多种算法思想。

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

A题:Déjà Vu


题意:

给定一个字符串 s s s,你要添加一个字符 a a a进去,使得这个字符串不是回文的,问是否可以?

题解:

1.如果字符串是只有 a a a构成的,那么无论插入到哪里,都是回文的。
2.如果不是只有 a a a构成的,那么把字符’a’插入首部或者尾部,一定有一种方案可以构造出不是回文的,只需要把这两种方案都判断一下就可以了。

AC代码:

#include "bits/stdc++.h"
using namespace std;
string s;
int t;
int main() {
	cin>>t;
	while(t--) {
		cin>>s;
		bool ok=false;
		for(int i=0; i<s.length(); i++)
			if(s[i]!='a')	ok=true;
		if(!ok)	puts("NO");
		else {
		puts("YES");
		s+='a';
		int len=s.length();
		for(int i=0;i<len;i++)
		if(s[i]!=s[len-i-1])	ok=false;
		if(!ok)	cout<<s<<"\n";
		else{
		cout<<'a';
		for(int i=0;i<len-1;i++)	cout<<s[i];
		cout<<"\n";
		} 
	}
}
	return 0;
}

B题:Flip the Bits


题意:

给了两个 01 01 01字符串 a a a, b b b,问是否通过多次操作使得将 a a a变成 b b b
你可以选择字符串 a a a的一个前缀取反,当且仅当这个前缀0的数目和1的数目相同。

题解:

先预处理出哪些位置为尾部的前缀0和1的数目相等。然后从最后一个字符开始,如果当前字符和 b b b字符串的对应位置不等,那么就必须改变这个字符,如果不能改变,就输出否。

AC代码:

#include "bits/stdc++.h"
using namespace std;
const int N=3e5+5;
char s1[N],s2[N];
int n,cnt[N],sum;
int main(){
	int t;
	cin>>t;
	while(t--){
	bool ok=1;sum=0;
	cin>>n;
	scanf("%s %s",s1+1,s2+1);
	for(int i=1;i<=n;i++)	cnt[i]=0;
	for(int i=1;i<=n;i++)
	if(s1[i]=='1')	cnt[i]=cnt[i-1]+1;
	else			cnt[i]=cnt[i-1]-1;	
	for(int i=n;i>=1;i--){
	if((s1[i]!=s2[i]&&sum%2!=0)||(s1[i]==s2[i]&&sum%2==0))	continue;
	if(cnt[i]!=0)	ok=false;
	sum++;	
	}
	if(ok)	puts("YES");
	else	puts("NO");
	}
	
	return 0;
} 

C题:Balance the Bits


题意:

给定一个的01序列,你要构造两个长度相同的括号序列,如果该位置的01序列为1,则括号序列该位置相同,否则不同。问是否能构造出来?

题解:

显然01序列的首尾都必须为1,且1的数目和0的数目都为偶数。从第2个位置到第n-1个位置中,如果1出现的次数为奇数,则’(’,否则为’)’。0的构造也一样。

AC代码:

#include "bits/stdc++.h"
using namespace std;
const int N=2e5+5;
int t,n,cnt;
char s[N];
char c1[N],c2[N];
int main() {
	cin>>t;
	while(t--) {
		cin>>n;
		cnt=0;
		scanf("%s",s+1);
		for(int i=1; i<=n; i++)
			if(s[i]=='0')	cnt++;
		if(n%2==1||s[1]!='1'||s[n]!='1'||cnt%2!=0) {
			puts("NO");
			continue;
		}
		int cnt1=0,cnt2=0;
		puts("YES");
		for(int i=1; i<=n; i++) {
			if(s[i]=='1') {
			if(i==1)			c1[1]=c2[1]='(';
			else if(i==n)		c1[n]=c2[n]=')';
			else{
			cnt1++;
			if(cnt1%2!=0)	c1[i]=c2[i]='(';
			else			c1[i]=c2[i]=')';	
			}
			} else {
			cnt2++;
			if(cnt2%2==0)	c1[i]='(',c2[i]=')';
			else			c1[i]=')',c2[i]='(';	
			}
		}
			for(int i=1;i<=n;i++)	cout<<c1[i];cout<<"\n";
		for(int i=1;i<=n;i++)	cout<<c2[i];cout<<"\n";

	}

	return 0;
}

D题:D - 3-Coloring


题意:

交互题:有三种颜色,构造一个矩阵染色,每次给你一个颜色,你需要在矩阵中选择一个方格,将该颜色染成非给定的颜色,构造的矩阵必须满足相邻的方格颜色不同。

题解:

把每个方格横纵坐标相加为奇数的染成1,为偶数的染成2。那么对于每次给定的颜色:
1.如果为1,那么就将偶数位置染色成2.
2.如果为2,那么就将奇数位置染色成1.
3.如果为3,那么随便将其中一个染色成对应的颜色。
如果奇数染色完了,或者偶数染色完了,就将另外的方格染色成对应的颜色或者3都是满足的。


AC代码:

#include "bits/stdc++.h"
using namespace std;
const int N=105;
int n,a[N][N],c1,c2,op,x,y,ans1,ans2;
vector<pair<int,int> >v[3];
int main(){
	cin>>n;
		
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	v[(i+j)%2+1].emplace_back(i,j);
	c1=v[1].size();
	c2=v[2].size();
	for(int T=1;T<=n*n;T++)
	{
	fflush(stdout);
	scanf("%d",&op);
	if(op==1){
	if(ans2<c2){
	x=v[2][ans2].first,y=v[2][ans2].second;
	ans2++;a[x][y]=2;	
	cout<<2<<" "<<x<<" "<<y<<"\n";
	}else{
	x=v[1][ans1].first,y=v[1][ans1].second;
	ans1++;a[x][y]=3;
	cout<<3<<" "<<x<<" "<<y<<"\n";
	}
	}else if(op==2){
	if(ans1<c1){
	x=v[1][ans1].first,y=v[1][ans1].second;
	ans1++;a[x][y]=1;
	cout<<1<<" "<<x<<" "<<y<<"\n";
	}else{
	x=v[2][ans2].first,y=v[2][ans2].second;
	ans2++;a[x][y]=3;		
	cout<<3<<" "<<x<<" "<<y<<"\n";
	}
		
	}else{
	if(ans1<c1){
	x=v[1][ans1].first,y=v[1][ans1].second;
	ans1++;a[x][y]=1;	
	cout<<1<<" "<<x<<" "<<y<<"\n";
	}else{
	x=v[2][ans2].first,y=v[2][ans2].second;
	ans2++;a[x][y]=2;	
	cout<<2<<" "<<x<<" "<<y<<"\n";
	}
	
	}
}
	return 0;
}

E题:E - Travelling Salesman Problem
题意:

给定1-n,从1出发去每个位置一次,并且回到1。问最少的路径花费是多少。每个点都有个 a [ i ] a[i] a[i] c [ i ] c[i] c[i],从 i i i j j j的花费为 m a x ( c [ i ] , a [ j ] − a [ i ] ) max(c[i],a[j]-a[i]) max(c[i],a[j]a[i]),问最少的花费是多少?

题解:

显然最少的花费至少是每个c[i]之和,每个点都出一次和回一次,那么一定是个环,我们将 a [ i ] a[i] a[i]从小到大排序,从排序后的1开始,如果到下一个点不需要更多的花费,那么就继续维护可以去到最远的地方距离m,然后继续去下一个点,如果不能直接到达,那么就从前面的点中花费最小的点去,因为从 a [ i ] a[i] a[i]大的点去小的点一定是不会有额外的花费的。详细见代码

AC代码:

#include "bits/stdc++.h"
using namespace std;
const int N=1e5+5;
int n,x,y,pos,vis[N];
long long ans,ma,m,tmp=1e18,cnt;
struct node {
	long long c,a,cz;
	int op;
} a[N];
bool cmp(node a,node b) {
	return a.a<b.a;
}
priority_queue<long long>q;
int main() {
	cin>>n;
	for(int i=1; i<=n; i++)
	cin>>a[i].a>>a[i].c,ans+=a[i].c,a[i].op=i,a[i].cz=a[i].a+a[i].c;
	sort(a+1,a+1+n,cmp);
	ma=a[1].c;
	m=a[1].a;
	cnt=a[1].cz;
	for(int i=2; i<=n; i++) {
		if(a[i].a<=ma+m) {					ma=max(ma,a[i].c+a[i].a-m);
		} else {	ans+=a[i].a-cnt;	ma=a[i].c,m=a[i].a;
		}
		cnt=max(cnt,a[i].cz);
	}

	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值