CF1799C Double Minimum Solution
题意:
给你一个字符串
-
\tt aab\to aba -
\tt abb\to bab -
\tt abbcc\to bbcca
设当前已经放到了字母
先看第一组,我们发现
再看第二组,我们猜想
但是你写完后发现过不了第
给几组手造样例,观察即猜得结论,写完交上去,A 了,所以结论正确 自己感性理解一下(证明见上):
整理一下:
首先从小到大枚举字母
- 当
cnt_u \geqslant 2 时 左右各放一个,然后回到判断语句; - 当
cnt_u = 1 时找到比
u 大的最小的字母v (cnt_v>0 )如果找不到,说明只剩
u 了,把最后一个空位填完就可以跑路了如果
cnt_v\geqslant2 且当前空位可以由u 和v 填满(即只剩u 和v 没填)那么就左右各放一个v 然后回到找v 的判断语句否则把
v 放在左边,u 放在右边,然后把剩下的字母升序排满剩下的空位,跑路
完结撒花!!!
这么简单的题(bushi的题解写了半个上午,如果觉得有帮助一定要点个赞啊 qwq
提交记录链接(完整代码)
int cnt[26];
char tmp[N], ans[N];
bool major(int Testcase = 1) {
scanf("%s", tmp);
memset(cnt, 0, sizeof cnt);
int n = 0;
for(; tmp[n]; n++) cnt[tmp[n] - 'a']++;
int l = 0, r = n - 1;
bool flag = 0;//flag = 1 表示要把剩下的字母升序排满剩下的空位
int u = 0, v = 0;
for(; u < 26; u++) {
/**/if(flag) {//tmd应该先判这个再判下面那个while,吃了一发罚时/kk
while(cnt[u])
ans[l++] = u/*;*/, cnt[u]--;
continue;
}
while(cnt[u] >= 2) ans[l++] = ans[r--] = u, cnt[u] -= 2;//左右各放一个 u
if(!cnt[u]) continue;
v = u + 1;
fore:;
for(; v < 26; v++) if(cnt[v] > 0) break;
if(v == 26) {//只剩 u 了,跑路!
ans[l++] = u;
break;
}
if(cnt[v] >= 2 && r - l + 1 == cnt[u] + cnt[v]) {
ans[l++] = ans[r--] = v, cnt[v] -= 2;
goto fore;
}
else
ans[l++] = v, ans[r--] = u, cnt[v]--, cnt[u]--, flag = 1;
}
for(int i = 0; i < n; i++) ans[i] += 'a';
//之前往字符数组里塞的都是数字,所以要转成 'a'~'z' 的字母
/**/ans[n] = 0;//否则多测输出会出锅
puts(ans);
return Testcase;
}