[Codeforces] Round #528 div1C div2E

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

贪心匹配,只有三种状态:压上界,压下界,不压界(出解)

#include<bits/stdc++.h>
using namespace std;
#define N 1000005

int n,k;
char a[N],b[N],c[N];
int go[30];
bool use[30];


inline void op()
{
	for (int i=0;i<k;i++) if (!~go[i]) for (int j=0;j<k;j++) if (!use[j]) {use[go[i]=j]=1;break;}
	for (int i=0;i<k;i++) putchar(go[i]+'a');
	puts("");
}

inline void solve()
{
	scanf("%d",&k);
	scanf("%s%s%s",c,a,b);
	n=strlen(a);
	for (int i=0;i<n;i++) a[i]-='a';
	for (int i=0;i<n;i++) b[i]-='a';
	for (int i=0;i<n;i++) c[i]-='a';
	memset(go,-1,sizeof(go));
	memset(use,0,sizeof(use));
	bool flag=0;
	for (int i=0;i<n;i++)
	{
		if (a[i]==b[i] && !flag)
		{
			if (~go[c[i]])
			{
				if (go[c[i]]!=a[i]) goto fail;
			}
			else
			{
				if (use[a[i]]) goto fail;
				go[c[i]]=a[i];
				use[a[i]]=1;
			}
		}
		else if (~go[c[i]])
		{
			if ((go[c[i]]>=b[i] && !flag) || go[c[i]]<a[i])
			{
				goto up;
			}
			if (go[c[i]]>a[i] && (go[c[i]]<b[i] || flag))
			{
				puts("YES");
				op();
				return;
			}	
		}
		else
		{
			for (int j=a[i]+1;j<(flag?k:b[i]);j++) if (!use[j])
			{
				use[j]=1;
				go[c[i]]=j;
				puts("YES"); 
				op();
				return;
			}
			if (use[a[i]]) goto up;
			go[c[i]]=a[i];
			use[a[i]]=1;
		}
		if (b[i]>a[i]) flag=1;
	}
	puts("YES");
	op();
	return;
	up:;
	memset(go,-1,sizeof(go));
	memset(use,0,sizeof(use));
	flag=0;
	for (int i=0;i<n;i++)
	{
		if (a[i]==b[i] && !flag)
		{
			if (~go[c[i]])
			{
				if (go[c[i]]!=a[i]) goto fail;
			}
			else
			{
				if (use[a[i]]) goto fail;
				go[c[i]]=a[i];
				use[a[i]]=1;
			}
		}
		else if (~go[c[i]])
		{
			if ((go[c[i]]<=a[i] && !flag) || go[c[i]]>b[i])
			{
				goto fail;
			}
			if (go[c[i]]<b[i] && (go[c[i]]>a[i] || flag))
			{
				puts("YES");
				op();
				return;
			}	
		}
		else
		{
			for (int j=b[i]-1;j>(flag?-1:a[i]);j--) if (!use[j])
			{
				use[j]=1;
				go[c[i]]=j;
				puts("YES"); 
				op();
				return;
			}
			if (use[b[i]]) goto fail;
			go[c[i]]=b[i];
			use[b[i]]=1;
		}
		if (b[i]>a[i]) flag=1;
	}	
	puts("YES");
	op();
	return;
	fail:puts("NO");
}

 
int main()
{
	int T;
	scanf("%d",&T);
	while (T--) solve();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值