Codeforces Round #650 (Div. 3)ABCD题解

题目链接:

A. Short Substrings
B. Even Array
C. Social Distance
D. Task On The Board

A. Short Substrings

题意:将字符串a的所有长度为2的子串连接形成新字符串,算出原字符串a
题解:直接跳过重复的即可

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
 
int t;
int main()
{
	cin>>t;
	while(t--){
		string a;
		cin>>a;
		cout<<a[0];
		for(int i=1;i<a.size();i++){
			cout<<a[i];
			if(i%2==1) i++;//去掉重复的
		}
		cout<<endl;
	}
	return 0;
 } 

B. Even Array

题意:交换数组中元素位置,使得下标与各元素同奇偶,如果可以输出交换次数,否则输出-1。
题解:分别记录下标为奇元素为偶的个数(q)和下标为偶元素为奇的个数(w),如果q=w,则输出q,反正-1。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a;
int t,n;
int main()
{
cin>>t;
while(t--){
  cin>>n;
  int q=0,w=0;
  for(int i=0;i<n;i++){
  	cin>>a;
  	if(i%2==0&&a%2==1) q++;
	  else if(i%2==1&&a%2==0) w++; 
  }
  if(q==w) cout<<q<<endl;
  else if(q!=w)  cout<<-1<<endl;
 
}
 return 0;
 } 

C. Social Distance

题意:给定一个二进制字符串,保证每个1之间间隔k个0,问可以放多少个1。
题解:谈论四种情况:
1、当前k+1个都为0时,就在第一个位置加1;
2、如果在中间有连续2k+1个0时,就在其中间加1;
3、如果在字符串尾部有连续k+1及以上 个0时,就在结尾加1;
4、如果字符串长度等于k,则答案为1;

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a,x;
int t,n,k;
int main()
{
   cin>>t;
while(t--){
    cin>>n>>k;
    int q=0,w=0,c=0;
    char x;
    for(int i=0;i<n;i++){
    	cin>>x;
    	if(x=='0')  w++,q++;
    	else if(x=='1') q=0;
		if(q==k+1&&i==k) c++,q=k;
		//第一种情况
		else if(q==2*k+1) c++,q=k;
		//第二种情况
	}
	if(q>=k+1) c++;
	//第三种情况
	if(w==n&&c==0) c++;
	//第四种情况
	cout<<c<<endl;
}
 return 0;
 } 

D. Task On The Board

题意:For example, if t = “abzb”, then:
since t1=‘a’, all other indices contain letters which are later in the alphabet, that is: b1=|1−2|+|1−3|+|1−4|=1+2+3=6;
since t2=‘b’, only the index j=3 contains the letter, which is later in the alphabet, that is: b2=|2−3|=1;
since t3=‘z’, then there are no indexes j such that tj>ti, thus b3=0;
since t4=‘b’, only the index j=3 contains the letter, which is later in the alphabet, that is: b4=|4−3|=1.
Thus, if t = “abzb”, then b=[6,1,0,1].
题解:注意b[j]=0的点,因为为0,所以他应该放的是最大的值。
我们只需要将最大的字母放在b[j]==0处,其他的地方都应该是小于他的,所以其他位置的数字会变成b[i]-=abs(i-j),以此类推,每一次为0的点都放剩下字母中最大且数目足够是字母,一直循环到结束即可。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int q,m,x,b[60],v[27];
string a;
int vis[60];
char da[60];
int main()
{
	cin>>q;
	while(q--){
		memset(v,0,sizeof v);
		memset(vis,0,sizeof vis); 
		memset(da,'0',sizeof da);
		cin>>a>>m;
		for(int i=1;i<=m;i++) scanf("%d",&b[i]);
		for(int i=0;i<a.size();i++) v[a[i]-'a'+1]++; 
		//下标表示字母的大小,值代表个数
		int num=0,zero=0,k=27;
		while(num!=m){//判断m个位置是否都放了
			zero=0;
			int c=0;
			for(int i=1;i<=m;i++) if(b[i]==0&&vis[i]==0) zero++;
			//记录当前为0的数目
			for(int i=k-1;i>0;i--) 
			if(v[i]>=zero) {k=i;break;}
			//寻找最大且数目足够的字母 
			for(int i=1;i<=m;i++) {
				if(b[i]==0&&vis[i]==0){
				vis[i]++;num++;
				//记录已经存放的位置和个数
				da[i]=k+'a'-1;
				//将字母存入
					}
		}
		for(int i=1;i<=m;i++){
			if(b[i]==0&&da[i]==k+'a'-1) 
			for(int j=1;j<=m;j++) 
			if(b[j]) b[j]-=abs(j-i);
			//其他位置都应该小于当前加入的字母,
			//所以前去位置差
		}
			}
		for(int i=1;i<=m;i++) cout<<da[i];
		cout<<endl;//输出
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Think-killer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值