arc113E Rvom and Rsrev

30 篇文章 0 订阅
17 篇文章 0 订阅

Description

Solution

  • 如果a偶数那么b一定不删,末尾为b则删完a,为a则将a花费最小的代价聚在最后。
  • 如果a为奇数,最后为a那么用最小代价将a聚集,最后为b则看b是否大于2个,以及前面是否有b来确定是否花费2个b使得开头有b-2个b。
  • 注意花费最小代价聚集可以先将所有大小为1的两两消掉。如果用了b-2的操作则看看最后一段a如果有1个是否可以往前面换。
  • 总之一点讨论,有点复杂。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define maxn 200005
using namespace std;

int T,n,i,j,k,a,b,s[maxn],d[maxn],cnt;

int doit(){
	int c0=0,c1=0;
	for(i=1;i<d[0];i++) if (d[i]==1) c1++; else c0++;
	return a-(c0+c1/2+c1%2)*2;
}

int main(){
	freopen("ceshi.in","r",stdin);
	freopen("ceshi.out","w",stdout);
	scanf("%d",&T); char ch=getchar();
	int id=0;
	while (T--){
		++id;
		while (ch!='a'&&ch!='b') ch=getchar();
		n=0; while (ch=='a'||ch=='b') s[++n]=ch,ch=getchar();
		a=b=0;
		for(i=1;i<=n;i++) if (s[i]=='a') a++; else b++;
		d[0]=0;
		for(i=1;i<=n;i++) if (s[i]=='a'&&(i==1||s[i-1]=='b')){
			d[++d[0]]=1;
			for(j=i+1;j<=n&&s[j]=='a';j++) d[d[0]]++;
		}
		if (a&1^1){
			while (b--) putchar('b');
			if (s[n]=='a'){
				cnt=doit();
				while (cnt--) putchar('a');
			}
		} else {
			if (s[n]=='a'){
				while (b--) putchar('b');
				cnt=doit();
				while (cnt--) putchar('a');
			} else {
				k=0;
				for(i=n;i>=1&&s[i]=='b';i--) k++;
				if (k<=2||b-k==0){
					for(i=1;i<=b-k;i++) putchar('b');
					putchar('a');
					for(i=1;i<=k;i++) putchar('b');
				} else {
					for(i=1;i<=b-2;i++) putchar('b');
					if (d[d[0]]==1){
						for(i=1;i<d[0];i++) if (d[i]>1&&(i>1||s[1]=='b')){
							swap(d[i],d[d[0]]);
							break;
						}
					}
					cnt=doit();
					while (cnt--) putchar('a');
				}
			}
		}
		putchar('\n');
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值