题解:AT_arc113_e [ARC113E] Rvom and Rsrev

· · 题解

看看样例,发现要对 ab 的位置和数量分讨。

A 表示一段极长连续 aB 表示一段极长连续 b。答案只有三种情况:

我们要做的操作是尽量把 b 向前挪动,直到挪不了或者挪了不优的时候才留下 a

考虑最终答案对应的 S 的情况。

AB

如果 S 里字母相同,什么都不做是最优的,否则会使字母数量变少。

--- ### $aB --- ### $BA

此时的答案,当 B 确定时,我们应该让 A 可能长。

S 结尾是 a

先除去最后一段 $A$,设剩下的 $|A|=1$ 的段有 $w_1$ 个,$|A|>1$ 的段有 $w_2$ 个。 我们每次操作,取最后一段 $A$ 和第一段 $A$ 的第一个位置,把第一段 $A$ 拼到最后一段,把最后一段 $B$ 转到前面。 这样会删掉 $2 \times w_2$ 个 $a$,使得 $S$ 中除了最后一段 $A$ 只剩下 $|A|=1$ 的段。 我们为了使剩下末尾的 $A$ 尽量长,就让 $|A|=1$ 的两两删,不够了再从末尾的 $A$ 里拿一个出来,这样操作会减掉 $2 \times \lceil \frac{w_1}{2} \rceil$ 个 $a$。 最后 $S$ 中的 $b$ 个数不变且被挪到了最前面,$a$ 减少了$2 \times (w_2 + \lceil \frac{w_1}{2} \rceil)$ 个。 #### $S$ 结尾是 $b 也就是说我们为了把后面的 $b$ 挪到前面去,一定会删掉两个 $b$。那我们可以先删 $b$,把一段 $a$ 挪到末尾,然后将 $b$ 向前挪并让末尾的 $A$ 尽可能长,这对于先删 $a$ 来说一定不劣。 我们选择操作一段 $A$ 的前后两个 $b$,把这段 $A$ 转到最后,然后就和上面 $S$ 结尾是 $a$ 的情况相同了。 注意如果 $S$ 开头不为 $b$,那么我们无法让第一段 $A$ 转到最后。 如果 $S = \dots B_1aB_2$,且 $|B_2| \le 2$,那么我们不能挪动中间的 $a$。因为如果操作完之后更优,应该满足 $|B_1|-1+|B_2|-1 > |B_1|$。 此时我们把前面的 $a$ 两两删掉,留下最后的一个 $a$ 即可。 对应答案 $BAB$。 ## 代码 ```cpp inline int w(int w1,int w2){ return 2*w2+w1+(w1&1); } inline void solve(){ int len = strlen(s+1); for(int i=1;i<=len;++i){ cnta[i] = cnta[i-1]+(s[i]=='a'); cntb[i] = cntb[i-1]+(s[i]=='b'); } if(!cnta[len] || !cntb[len]){ for(int i=1;i<=len;++i) putchar(s[i]); return ; } if(s[len]=='b' && !(cnta[len]&1)){ for(int i=1;i<=cntb[len];++i) putchar('b'); return ; } if(cnta[len-cntb[len]]==cnta[len] && (cnta[len]&1)){ putchar('a'); for(int i=1;i<=cntb[len];++i) putchar('b'); return ; } if(s[len]=='b'){ int lasa = len; for(int i=len;i;--i){ if(s[i]^'b'){ lasa = i; break; } } if(len-lasa<=2){ for(int i=1;i<=cntb[lasa];++i) putchar('b'); putchar('a'); for(int i=cntb[lasa]+1;i<=cntb[len];++i) putchar('b'); return ; } } int las = 0,w1 = 0,w2 = 0; for(int i=1;i<=len;++i){ if(s[i]=='b'){ if(i-1-(las+1)+1==1) ++w1; else if(i-1-(las+1)+1>1) ++w2; las = i; } } if(s[len]=='a'){ for(int i=1;i<=cntb[len];++i) putchar('b'); for(int i=1;i<=cnta[len]-w(w1,w2);++i) putchar('a'); return ; } int tw = 0; if(s[1]=='b')tw = Min(w(w1-1,w2),w(w1,w2-1)); else{ int f = -1; for(int i=1;i<=len;++i){ if(s[i]=='b'){ f = (i>3); break; } } if(f){ if(w2==1) tw = w(w1-1,w2); else tw = Min(w(w1-1,w2),w(w1,w2-1)); } else{ if(w1==1) tw = w(w1,w2-1); else tw = Min(w(w1-1,w2),w(w1,w2-1)); } } for(int i=1;i<=cntb[len]-2;++i) putchar('b'); for(int i=1;i<=cnta[len]-tw;++i) putchar('a'); } ```