CF794C Naming Company 题解

题目链接
我的洛谷Blog

题目大意

A,B 两人各有一个长度为 n n n 的,由小写字母构成的字符串 s , t s,t s,t,还有一个长度为 n n n,初始时由 ? 组成的目标串 f f f

现在,A和B轮流进行如下操作:

  1. 在自己的字符串中选出一个字符 x x x
  2. f f f 中的一个 ? 替换为 x x x
  3. x x x 从自己的字符串中删去。
    f f f 中没有 ? 时游戏结束。

A 的目标是让 f f f 的字典序尽量小,而 B 的目标是让字典序尽量大。
现在设 A 为先手,你需要求出游戏结束后的 f f f

注意: s , t s,t s,t 中可能有多个重复的字符,每次只删除一个

解题思路

一个显而易见的贪心思路,分别让 s , t s,t s,t 升序和降序排序。
然后,每个人尽可能把自己字符串中前面的字符放在 f f f 的前面,从而最大/最小化 f f f 的字典序。

如果你是这么写的话,恭喜你 WA on test 6

这里来举一个反例:

s="pqrs"
t="dcba"

如果在这种情况下,还是按照上面的方法,那你会发现 A,B 在互相帮助QwQ。也就是说,两方的操作会对对方的目标产生好处。
那么,我们的最优方案就变成了止损。由于在字符串越前面的字符,对字典序的影响就越大,所以,我们就尽可能地把对对方有利的字符往后放。
比如对于这组数据,A 就需要尽可能地把字典序大的字母往 f f f 的后面放,B 同理。

最后,我们将两个思路结合:
s i < t i s_i<t_i si<ti 时,按第一种方法贪心。
否则,就按第二种方法贪心。

有一些实现上的小细节,这里就不写了,直接上代码。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int Maxn=3e5+10;
char s[Maxn];
int a[Maxn],b[Maxn];
int f[Maxn];
int n;
inline bool cmp(int x,int y)
{
	return x>y;
}
int main()
{
	// freopen("in.txt","r",stdin);
	scanf("%s",s+1);
	n=strlen(s+1);
	for(int i=1;i<=n;++i)
	a[i]=s[i]-'a';
	scanf("%s",s+1);
	for(int i=1;i<=n;++i)
	b[i]=s[i]-'a';
	sort(a+1,a+1+n);
	sort(b+1,b+1+n,cmp);
	int x=0,y=0,pos=n;
	for(int i=1;i<=n;++i)
	{
		if(a[x+1]>=b[y+1]){pos=i-1;break;}
		if(i & 1)f[i]=a[++x];
		else f[i]=b[++y];
	}
	x=y=(n>>1)+1;
	if((n & 1))++x;
	for(int i=n;i>pos;--i)
	{
		if((pos+(n-i+1)) & 1)f[i]=a[--x];
		else f[i]=b[--y];
	}
	for(int i=1;i<=n;++i)
	putchar(f[i]+'a');
	putchar('\n');
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值