专栏文章

[CF1799C] Double Lexicographically Minimum 题解

CF1799C题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min9mb3g
此快照首次捕获于
2025/12/01 22:49
3 个月前
此快照最后确认于
2025/12/01 22:49
3 个月前
查看原文
字典序最小化的一个一般做法就是按位确定。设 tit_i 翻转后对应 ttoit_{to_i},从左到右逐位确定 tt,若当前确定 ti=ct_i=c,其中 cc 是还剩有的最小字符,为了使 tt 翻转后 tit'_i 不变为一个更大的字符,需要尽可能使得 ttoi=ct_{to_i}=c
如果能够满足,就向两端填入 cc。否则,一个明显的想法是,设次小字符为 dd,则令 ti=d,ttoi=ct_i=d,t_{to_i}=c,这样保证了 tmaxt_{\max} 一定为 tt 本身,然后剩下的字符从小到大从左往右填进去。
但是,设次次小字符为 ede\neq d,若 ee 不存在,可以将 cc 挪到字符串中央,显然这样是最优的。否则,cc 进行移动时需要在 cc 曾经停留的地方放入 dd 来保证还有可能使得 tmax=tt_{\max}=t,此时 ee 一定会向前移动,一定不优。于是分讨这样的 ee 是否存在即可。
codeCPP
#include<bits/stdc++.h>
#define pb emplace_back
#define mp make_pair
using namespace std;
typedef unsigned long long ll;
typedef __int128 LL;
const ll maxn=200007,ee=1e18;
ll n;
string s,ans;
void solve(void){
	for(ll i=0;2*i+1<n;i++){
		if(s[2*i]==s[2*i+1]) ans[i]=ans[n-1-i]=s[2*i];
		else{
			ans[i]=s[2*i+1],ans[n-1-i]=s[2*i];
			if(2*(i+1)>=n) return;
			if(s[n-1]==s[2*i+1]){
				for(ll j=i;j<=n-1-i;j++) ans[j]=s[n-1];
				ans[n/2]=s[2*i];
				return;
			}
			for(ll j=i+1,c=2*i+2;j<n-1-i;j++,c++) ans[j]=s[c];
			return;
		}
	}
	if(n&1) ans[n/2]=s[n-1];
}
int main(void){
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	ios::sync_with_stdio(0),cin.tie(0);
	ll T=1; cin>>T;
	for(;T--;){
		cin>>s,n=s.length();
		ans.resize(n);
		sort(s.begin(),s.end());
		solve();
		cout<<ans<<"\n";
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...