Codeforces Round #732 (Div. 2)

这篇博客探讨了三道编程竞赛题目,涉及数组的操作以达成特定条件,字符串的比较和重组,以及序列排序的特殊策略。第一题要求通过特定操作使两个数组相等,第二题需要找出未被使用的原始字符串,第三题则研究如何在保持序列增序的同时保持元素方向。解决方案包括动态规划、字符计数和奇偶位置的策略分析。
摘要由CSDN通过智能技术生成

https://codeforces.com/contest/1546/problem/A

A. AquaMoon and Two Arrays

题意:给你一个数组a以及一个数组b,在一次操作中,你可以让a[i]+1且a[j]-1,i≠j。你可以操作很多次,直到a数组完全等于b数组,问你能不能完成操作,如果不能输出-1;如果可以,请输出最少操作次数。

思路:让a[i]与b[i]作比较,如果a[i]比较大那么就放出-1的操作里,如果相等直接跳过,如果a[i]比较小,放入+1的操作里。然后再判断+1的操作次数与-1的操作次数是否相同,如果不同那么我们就无法完成,否则输出操作次数以及分别输出每次操作的是哪两个序号。

代码:

#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define hh 0x3f3f3f3f
const int MAXX=2e5+5;
using namespace std;
inline int read()
{
	ll s=0,f=1;
	char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+c-'0';c=getchar();}
	return s*f;
}
int jian[100005],jia[100005],jian_,jia_,a[105],b[105];
void solve()
{
	int n;
	for(int i=1;i<=10000;i++)
	{
		jian[i]=0;
		jia[i]=0;
	}
	cin>>n;
	jian_=0,jia_=0;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)cin>>b[i];
	for(int i=1;i<=n;i++)
	{
		if(a[i]==b[i])continue;
		else if(a[i]>b[i])
		{
			int temp=a[i]-b[i];
			while(temp)
			{
				jian[++jian_]=i;
				temp--;
			}
		}
		else
		{
			int temp=b[i]-a[i];
			while(temp)
			{
				jia[++jia_]=i;
				temp--;
			}
		}
	}
	if(jian_!=jia_)
	{
		cout<<"-1"<<endl;
	}
	else
	{
		cout<<jian_<<endl;
		for(int i=1;i<=jian_;i++)
		{
			cout<<jian[i]<<" "<<jia[i]<<endl;
		}
	}
}
int main()
{
	ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}	
	return 0;
}

https://codeforces.com/contest/1546/problem/B

B. AquaMoon and Stolen String

题意:给你长度为m的n串原字符串(n是奇数),然后再拿出n-1串字符串然后让他们两两随机交换位置,并给你。问:原字符串里的哪一串没被使用过。

思路:思考1-m位置他们再怎么交换位置都不变,因此我们可以用二维数组f[i][j]分别存他们的位置,i表示位置,j字符,不如abc,a存在f[1][97]的位置,b存在f[2][98]的位置,c存在f[3][99]的位置。。。

接下来是长度为m,n-1行的字符串,从存好的f[i][j]里取出来,取完后每个位置绝对会只剩下一个字符,这个字符就是对应的答案,输出这个就行了。

代码:

#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define hh 0x3f3f3f3f
const int MAXX=2e5+5;
using namespace std;
inline int read()
{
	ll s=0,f=1;
	char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+c-'0';c=getchar();}
	return s*f;
}
int f[MAXX][200];
char s[MAXX];
int n,m;
void solve()
{
	
	cin>>n>>m;
	for(int i=1;i<=m;i++)//初始化 
	{
		for(int j='a';j<='z';j++)
		{
			f[i][j]=0;
		}
	}
	for(int i=1;i<=n;i++)//先输入原串 
	{
		cin>>s+1;
		for(int j=1;j<=m;j++)
		{
			f[j][s[j]]++;
		}
	}
	for(int i=1;i<=n-1;i++)//删去原串 
	{
		cin>>s+1;
		for(int j=1;j<=m;j++)
		{
			f[j][s[j]]--;
		}
	}
	for(int i=1;i<=m;i++)//输出剩下的字符串 
	{
		for(int j='a';j<='z';j++)
		{
			if(f[i][j]==0)continue;
			cout<<char(j);
			break;
		}
	}
	cout<<endl<<endl;
}
int main()
{
	ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

https://codeforces.com/contest/1546/problem/C

C. AquaMoon and Strange Sort

题意:给你n个数,开始的时候每个数都是向右的,你可以进行任意次操作,交换a,b的位置,但是他们的方向也会变化,直到他们成为单调递增的序列。问你能不能在操作完成后他们的方向还是向右。

思路:我们不难发现奇数之间的交换或者是偶数之间的交换他们的方向都是不变的,比如,4,3,2,5(4,2都是奇数位;3,5都是偶数位),我们可以通过偶数位3作为中间媒介,交换4和2,因此,3、2、4都交换了两次他们的方向都没变。

那么可以用一个奇数位数组以及偶数位数组装他们:

for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(i%2==0)ou[a[i]]++;
        else ji[a[i]]++;
    }

然后在通过sort排序,进行同上的操作,如果 奇数位或者偶数位的大小小于0,那么就说明排完序后的方向不可能都向右,反之成立。

代码:

#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define hh 0x3f3f3f3f
const int MAXX=1e5+5;
using namespace std;
inline int read()
{
	ll s=0,f=1;
	char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+c-'0';c=getchar();}
	return s*f;
}
int ji[MAXX],ou[MAXX],a[MAXX],n,pd;
void solve()
{
	for(int i=1;i<=MAXX;i++)//初始化 
	{
		ji[i]=0;ou[i]=0;
	}
	cin>>n;
	pd=1;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		if(i%2==0)ou[a[i]]++;//偶数位 
		else ji[a[i]]++;//奇数位 
	}
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++)
	{
		if(i%2==0)ou[a[i]]--;//偶数位 
		else ji[a[i]]--;//奇数位 
		if(ji[a[i]]<0||ou[a[i]]<0)//不成立的情况 
		{
			pd=0;break;
		}
	}
	if(pd)cout<<"YES\n";
	else cout<<"NO\n";
}
int main()
{
	ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	} 
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值