目录
A. Three Pairwise Maximums
- 题意
x=max(a,b)
y=max(a,c)
z=max(b,c)
给你 x、y、z 问 a、b、c 是否存在并输出任意答案 - 输入
5
3 2 3
100 100 100
50 49 49
10 30 20
1 1000000000 1000000000
- 输出
YES
3 2 1
YES
100 100 100
NO
NO
YES
1 1 1000000000
- 解题思路
令a<=b<=c则
x=max(a,b)=b
y=max(a,c)=c
z=max(b,c)=c
所以先将x、y、z从小到大排序,若x<y=z则存在且a=x b=x c=y - 代码
#include<stdio.h>
#include<algorithm>
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
- 题意
给你一个由两个长为n的置换合并的数列,求原置换
合并不会改变原置换中的顺序 - 输入
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 2
1 3 4 2
1 2 3 4 5
1 2 3
2 3 4 1
- 解题思路
标记+去重,只留下1-n第一次出现的 - 代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
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
- 题意
给你一个长度为n的数列,问至少要删去多长的前缀才能使它是一个好的数列。
一个好的数列的定义:每次取该数列的头或尾放到另一个数列c中,直至该数列的数全取完,且c是单调递增的。 - 输入
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
- 输出
0
4
0
2
3
- 解题思路
从后往前看,找到一个山峰(先递增再递减),删去多余的 - 代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
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
- 题意:给你一个长为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
- 输入
6
8
bbdcaaaa
8
asdfghjk
8
ceaaaabb
8
bbaaddcc
1
z
2
ac
- 输出
0
7
4
5
1
1
- 解题思路
根据题意可知a-good是递归定义出来的,所以求解也用递归。dfs 枚举所有可能的情况 ,左边一半选当前字符还是右边一半取当前字符,计算出不同字符数,取较小的。 - 代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
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;
}