ARC113E Rvom and Rsrev

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

用 表示一段极长连续 , 表示一段极长连续 。答案只有三种情况:

  1. 或者 ;

  2. ;

  3. ;

  4. 。

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

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


或

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

不满足前面的所有条件。如果 且 有偶数个,我们要让 尽量向前挪动,直接把 删完即可。


不满足前面的所有条件。如果 ,且 为奇数时, 删不完,让 尽量向前挪动,那就剩下一个 最优。


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

结尾是

不满足前面的所有条件。如果 结尾是 ,那么我们操作会是一直删 使 向前挪,并且末尾留下 尽量长。

先除去最后一段 ,设剩下的 的段有 个, 的段有 个。

我们每次操作,取最后一段 和第一段 的第一个位置,把第一段 拼到最后一段,把最后一段 转到前面。
这样会删掉 个 ,使得 中除了最后一段 只剩下 的段。

我们为了使剩下末尾的 尽量长,就让 的两两删,不够了再从末尾的 里拿一个出来,这样操作会减掉 个 。

最后 中的 个数不变且被挪到了最前面, 减少了 个。

结尾是

不满足前面的所有条件。如果 结尾是 且有奇数个 ,假如我们直接先删 使 ,那么我们再删两个 把 挪到后面更优。

也就是说我们为了把后面的 挪到前面去,一定会删掉两个 。那我们可以先删 ,把一段 挪到末尾,然后将 向前挪并让末尾的 尽可能长,这对于先删 来说一定不劣。

我们选择操作一段 的前后两个 ,把这段 转到最后,然后就和上面 结尾是 的情况相同了。

注意如果 开头不为 ,那么我们无法让第一段 转到最后。

如果 ,且 ,那么我们不能挪动中间的 。因为如果操作完之后更优,应该满足 。
此时我们把前面的 两两删掉,留下最后的一个 即可。
对应答案 。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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');
}