CF1689A题解

题意简述

给定字符串 \(a\)\(b\),每次从 \(a\) 串或 \(b\) 串中选出一个字符加入 \(c\) 串,要求 \(c\) 串的字典序最小。特别地,在 \(c\) 串中不能出现连续 \(k\) 次来源相同的字符。

思维路径

由于字符是随意选取的,易于发现每次选 \(a\) 串中字典序最小的字符或者 \(b\) 串中字典序最小的字符一定比其他方案更优,因此先对 \(a\) 串和 \(b\) 串按照字典序排序。

接下来考虑新加入 \(c\) 串的字符,假设对于两个串来说分别是加入 \(a_i\)\(b_j\),有如下两种情况。

  • 若无论加入哪个串都不会出现连续 \(k\) 个来源相同的字符,那么选 \(a_i\)\(b_j\) 字典序更小的那一个。
  • 若加入某个串的字符会出现连续 \(k\) 个来源相同的字符,那么选另一个串的字符。

最终某一个串被选完的时候立刻结束,此时的 \(c\) 串就是答案。

AC 代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=109;
ll T,n,m,k;
char a[N],b[N],c[N*2];
ll nw,num,cnt;

void input(){
	cin>>n>>m>>k;
	for(ll i=1;i<=n;i++) cin>>a[i];
	for(ll j=1;j<=m;j++) cin>>b[j];
}

void solve(){
	sort(a+1,a+n+1);
	sort(b+1,b+m+1);
	cnt=0;
	ll j=1;
	nw=0; num=0;
	for(ll i=1;i<=n;i++){
		while(num==k||(j<=m&&a[i]>b[j])){
			c[++cnt]=b[j];
			j++;
			if(nw==2){
				num++;
			}
			else{
				nw=2; num=1;
			}
			if(num==k) break;
		}
		if(j>m) break;
		c[++cnt]=a[i];
		if(nw==1){
			num++;
		}
		else{
			nw=1; num=1;
		}
	}
	for(ll i=1;i<=cnt;i++) cout<<c[i]; cout<<"\n";
}

int main(){
	cin>>T;
	while(T--){
		input();
		solve();
	} 
	return 0;
}
posted @ 2024-01-24 14:37  lemon-cyy  阅读(10)  评论(0编辑  收藏  举报