Codeforces Round #656 (Div. 3) A,B,C,D,(其他待补)

目录

  • [ A. Three Pairwise Maximums](https://codeforces.ml/contest/1385/problem/A)
  • [B. Restore the Permutation by Merger](https://codeforces.ml/contest/1385/problem/B)
  • [C. Make It Good](https://codeforces.ml/contest/1385/problem/C)
  • [D. a-Good String](https://codeforces.ml/contest/1385/problem/D)

A. Three Pairwise Maximums

  1. 题意
    x=max(a,b)
    y=max(a,c)
    z=max(b,c)
    给你 x、y、z 问 a、b、c 是否存在并输出任意答案
  2. 输入

5
3 2 3
100 100 100
50 49 49
10 30 20
1 1000000000 1000000000

  1. 输出

YES
3 2 1
YES
100 100 100
NO
NO
YES
1 1 1000000000

  1. 解题思路
    令a<=b<=c则
    x=max(a,b)=b
    y=max(a,c)=c
    z=max(b,c)=c
    所以先将x、y、z从小到大排序,若x
  2. 代码
#include
#include
using namespace std;
int main()
{
	int t,a[3];
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%d",&a[0],&a[1],&a[2]);
		sort(a,a+3);
		if(a[1]==a[2])
		{
			printf("YES\n");
			printf("%d %d %d\n",a[0],a[0],a[2]);
		}
		else printf("NO\n");
	}
	return 0;
} 

B. Restore the Permutation by Merger

  1. 题意
    给你一个由两个长为n的置换合并的数列,求原置换
    合并不会改变原置换中的顺序
  2. 输入

5
2
1 1 2 2
4
1 3 1 4 3 4 2 2
5
1 2 1 2 3 4 3 5 4 5
3
1 2 3 1 2 3
4
2 3 2 4 1 3 4 1

  1. 输出

1 2
1 3 4 2
1 2 3 4 5
1 2 3
2 3 4 1

  1. 解题思路
    标记+去重,只留下1-n第一次出现的
  2. 代码
#include
#include
#include
using namespace std;
int t,n,x,a[110],b[55],cnt;
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		cnt=0;
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		for(int i=1;i<=2*n;i++)
		{
			scanf("%d",&x);
			if(!b[x])
			{
				b[x]++;a[++cnt]=x;
			}
		}
		for(int i=1;i<=cnt;i++)printf("%d ",a[i]);
		printf("\n");
	}
	return 0;
}

C. Make It Good

  1. 题意
    给你一个长度为n的数列,问至少要删去多长的前缀才能使它是一个好的数列。
    一个好的数列的定义:每次取该数列的头或尾放到另一个数列c中,直至该数列的数全取完,且c是单调递增的。
  2. 输入

5
4
1 2 3 4
7
4 3 3 8 4 5 2
3
1 1 1
7
1 3 1 4 5 3 2
5
5 4 3 2 3

  1. 输出

0
4
0
2
3

  1. 解题思路
    从后往前看,找到一个山峰(先递增再递减),删去多余的
  2. 代码
#include
#include
#include
using namespace std;
int const N=2e5+5;
int t,n,a[N];
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)scanf("%d",&a[i]);
		int i=0,j=0;
		for(i=n-1;i>=1;i--)
			if(a[i]<a[i+1])break;
		
		for(j=i;j>=1;j--)
			if(a[j]>a[j+1])break;
		printf("%d\n",j);
	}
	return 0;
}

D. a-Good String

  1. 题意:给你一个长为n=2k的仅有小写字母组成的字符串s,求最少改变几个字符使它成为a-good
    a-good的定义如下:
  • n==1 s1=a
  • n>=1 s的前半部分全为a后半部分为(a+1)-good
  • n>=1 s的前半部分为(a+1)-good后半部分全为a
  1. 输入

6
8
bbdcaaaa
8
asdfghjk
8
ceaaaabb
8
bbaaddcc
1
z
2
ac

  1. 输出

0
7
4
5
1
1

  1. 解题思路
    根据题意可知a-good是递归定义出来的,所以求解也用递归。dfs 枚举所有可能的情况 ,左边一半选当前字符还是右边一半取当前字符,计算出不同字符数,取较小的。
  2. 代码
#include
#include
#include
using namespace std;
int const N=2e5;
char s[N];
int t,n;
int dfs(int l,int r,char ch)
{
	if(l==r)//n=1的情况
	{
		if(ch==s[l])return 0;//不需要修改
		return 1; //需要修改
	}
	int cnt1=0,cnt2=0,x=(l+r)/2;
	for(int i=l;i<=x;i++)
		if(ch!=s[i])cnt1++;
	for(int i=x+1;i<=r;i++)
		if(ch!=s[i])cnt2++;
	return min(dfs(l,x,ch+1)+cnt2,cnt1+dfs(x+1,r,ch+1));
	//分别表示 改前半段为(ch+1)-good后半段为ch 与 改前半段为ch后半段为(ch+1)-good 的情况取最优
}
int main()
{
	scanf("%d\n",&t);
	while(t--)
	{
		scanf("%d\n",&n);
		scanf("%s",s+1);
		printf("%d\n",dfs(1,n,'a'));
	}
	return 0;
} 

你可能感兴趣的:(Codeforces)