[AGC036E] ABC String

又是一个逐步简化的模型,好烦了又不会做这种题了呜啊呜啊。


首先相邻且相同的字符,我们可以缩在一起。

不妨假设 cacbcc,我们考虑逐步删除来达到三个字符相同的情况。

按照 A 将整个字符串划分成若干段,每一段一定形如 BC 交错的情形。

注意到中间字符串长度大于等于 3 时删除 BC 原串仍然满足相邻字符不相同这个性质,猜测 cb=cc 时可以取到上界。

证明:若一直删除 BC,最后两个 A 之间至多两个字符,两边至多一个字符,那么 cb+cc2(ca1)+2=2ca,而一开始 cb+cc2ca,那么删除过程中一定会满足 cb+cc=2ca


那么我们现在的目标就是保证 ca 尽量大的情况下使得 cb=cc,首先如果说可以单独删除一个 C 一定会删除的,当两个 A 之间的字符串长度大于等于 2 的时候就可以将两边的 C 字符删掉。

如果还是不行的话,那么单个 C 的段一定比 B 的段多,我们一直删除 AC/CA 即可。

#include<bits/stdc++.h>
using namespace std;
#define N 1000005
char s[N];
int n,m,pos[3];
pair<int,int> mp[3];
int a[N],b[N];
void copy(){for(int i=1;i<=n;i++)b[i]=a[i];m=0;}
void output(){for(int i=1;i<=n;i++)printf("%d",a[i]);puts("");}
void makeeq(){
	int x=0,y=0,z=0;
	for(int i=1;i<=n;i++)
		if(a[i]==0)++x;
		else if(a[i]==1)++y;
		else ++z;
	copy();
	for(int l=1,r=1;l<=n;l=++r)
		if(b[l]!=0){
			while(r<n&&b[r+1]!=0)++r;
			if(r-l+1>=2){
				if(b[l]==2){
					if(z>y)--z;
					else a[++m]=b[l];
				}else a[++m]=b[l];
				for(int i=l+1;i<r;i++)a[++m]=b[i];
				if(b[r]==2){
					if(z>y)--z;
					else a[++m]=b[r];
				}else a[++m]=b[r];
			} 
			else if(z>y&&b[l]==2&&(l==1||r==n))--z;
			else a[++m]=b[l];
		}else a[++m]=b[l];
	n=m;
	if(z==y)return;
	copy();
	for(int i=1;i<=n;i++){
		if(z>y&&i<=n-1&&(b[i]==0&&b[i+1]==2||b[i]==2&&b[i+1]==0))++i,--z;
		else a[++m]=b[i];
	}
	n=m;
}
void getup(){
	int x=0,y=0,z=0;
	for(int i=1;i<=n;i++)
		if(a[i]==0)++x;
		else if(a[i]==1)++y;
		else ++z;
	copy();
	for(int l=1,r=1;l<=n;l=++r)
		if(b[l]!=0){
			while(r<n&&b[r+1]!=0)++r;
			while(r-l+1>2&&y>x)l+=2,--y;
			if(y>x&&r-l+1==2&&(l==1||r==n))l+=2,--y;
			for(int i=l;i<=r;i++)a[++m]=b[i];
		}
		else a[++m]=b[l];
	n=m;
}
int main(){
	for(int i=0;i<3;i++)mp[i].second=i;
	scanf("%s",s+1);n=strlen(s+1);
	for(int i=1;i<=n;i++)a[i]=s[i]-'A';
	copy();
	for(int i=1;i<=n;i++)if(i==1||b[i]!=b[i-1])a[++m]=b[i],++mp[b[i]].first;n=m;
	sort(mp,mp+3);
	for(int i=0;i<3;i++)pos[mp[i].second]=i;
	for(int i=1;i<=n;i++)a[i]=pos[a[i]];
	makeeq();
	getup();
	assert(n%3==0);
	for(int i=1;i<=n;i++)printf("%c",mp[a[i]].second+'A');
}
posted @   xcyyyyyy  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示