agc036E - ABC String

题目大意

题解

乱搞题,比D简单

首先把相邻的去重,接着按出现次数从大到小标成012,由于0很多所以只考虑12

如果有11或22,则中间一定要插一个0,可能必要的0会多于1和2所以要成对删1122(删其中一个)

先把12出现次数调整相同,然后开始删,如果1122不够则只可能是完全删完,那么删掉1212串末尾的那个即可,最后再把多出来的0补上

(因为11和22的个数最多相差1,证明考虑把串变成环,则1122个数相同,接着变成链则最多一个)

注意到上面的操作基本没有考虑0,如果0小于1或2就挂了,当然不可能

简单证明:如果一开始必要的0多于12,则删的过程中每次0减2,1和2减1,最后够了的时候刚好必要0=1个数=2个数,只保留必要0

如果一开始必要0不大于12,则通过删非必要0把0个数变成12个数

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;

struct type{char ch;int s;} c[3];
int a[1000001],n,i,j,k,l,s[2],ls,S;
bool bz[1000001];
char st[1000001];

bool cmp(type a,type b) {return a.s>b.s;}

int main()
{
	#ifdef file
	freopen("agc036E.in","r",stdin);
	#endif
	
	scanf("%s",st+1),n=strlen(st+1);l=0;
	fo(i,1,n) if (st[i]!=st[i-1]) st[++l]=st[i];
	n=l;
	
	c[0].ch='A',c[1].ch='B',c[2].ch='C';
	fo(i,1,n) ++c[st[i]-'A'].s;
	sort(c,c+3,cmp);
	fo(i,1,n) if (st[i]==c[0].ch) a[i]=0; else if (st[i]==c[1].ch) a[i]=1; else a[i]=2;
	if (!c[2].s) return 0;
	
	fo(i,1,n)
	if (a[i])
	{
		if (ls==a[i]) ++s[ls-1];
		ls=a[i];
	}
	while (c[1].s>c[2].s) --c[1].s,--s[0];
	if (s[0]<0) {fd(l,n,1) if (a[l]==1) break;--l;s[0]=0;}
	else l=n;
	
	S=c[2].s;
	while (s[0]+s[1]>S) --s[0],--s[1],--S;
	S-=s[0]+s[1];
	ls=0;
	fo(i,1,l)
	if (a[i])
	{
		if (ls==a[i])
		{
			if (s[ls-1])
			--s[ls-1],bz[i]=1;
		}
		else bz[i]=1;
		ls=a[i];
	}
	ls=0;
	fo(i,1,l)
	if (a[i] && bz[i])
	{
		if (S || ls && a[ls]==a[i])
		{
			fo(j,ls+1,i) if (!a[j]) break;
			if (j<=i)
			{
				if (a[ls]!=a[i]) --S;
				bz[j]=1;
			}
		}
		ls=i;
	}
	if (S) {fo(i,ls+1,n) if (!a[i]) break;bz[i]=1;}
	
	fo(i,1,n) if (bz[i]) putchar(c[a[i]].ch);
	putchar('\n');
}
posted @ 2020-11-15 10:21  gmh77  阅读(150)  评论(0编辑  收藏  举报