[ARC209B] Minimize Even Palindrome
Genius_Star · · 题解
找性质题。
思路:
显然,发现一个偶回文串中间会出现两个相邻的相同字符。
先考虑能否构造出一个串相邻字符不同,显然充要条件是
- 具体构造考虑,每次选择两个出现次数最多的字符插到后面;实现的话可以每次扫一遍或者用堆做是
O(n|S|) 或者O(n \log |S|) 。
否则
但是这样还不是最优,因为考虑 aabaabaa,此时存在着以中间
同时注意到对于两个偶回文串
于是判断一下偶数段数量的奇偶性即可,如果是奇数则剩下一个偶数段放到最后也不会造成贡献。
时间复杂度是
完整代码:
#include<bits/stdc++.h>
#define ls(k) k << 1
#define rs(k) k << 1 | 1
#define fi first
#define se second
#define add(x, y) ((x + y >= mod) ? (x + y - mod) : (x + y))
#define dec(x, y) ((x - y < 0) ? (x - y + mod) : (x - y))
#define popcnt(x) __builtin_popcount(x)
#define open(s1, s2) freopen(s1, "r", stdin), freopen(s2, "w", stdout);
using namespace std;
typedef __int128 __;
typedef long double lb;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
const int N = 2e5 + 10, M = 26;
inline ll read(){
ll x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-')
f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return x * f;
}
inline void write(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
int T, n, mx, id;
char s[N];
int cnt[M];
inline void solve1(){
priority_queue<pair<int, char>> Q;
for(int i = 0; i < M; ++i)
if(cnt[i])
Q.push({cnt[i], (char)('a' + i)});
while((int)Q.size() >= 2){
auto x = Q.top();
Q.pop();
auto y = Q.top();
Q.pop();
putchar(x.se);
putchar(y.se);
if(x.fi > 1)
Q.push({x.fi - 1, x.se});
if(y.fi > 1)
Q.push({y.fi - 1, y.se});
}
if(!Q.empty()){
assert(Q.top().fi == 1);
putchar(Q.top().se);
}
putchar('\n');
}
inline void solve2(){
int p = n - mx + 1;
int y = mx % p, x = p - y;
int len = mx / p;
assert(len * x + (len + 1) * y == mx);
int c1 = 0, c2 = 0, c3 = 0, c4 = 0, end = 0; // len - 1, len, len + 1, len + 2, end
if(len & 1){
c2 += x;
c2 += (y >> 1);
c4 += (y >> 1);
if(y & 1)
end = len + 1;
}
else{
c3 += y;
c1 += (x >> 1);
c3 += (x >> 1);
if(x & 1)
end = len;
}
stack<char> stk;
for(int i = 1; i <= n; ++i)
if(s[i] - 'a' != id)
stk.push(s[i]);
while(c1--){
for(int i = 1; i <= len - 1; ++i)
putchar('a' + id);
if(stk.size())
putchar(stk.top()), stk.pop();
}
while(c2--){
for(int i = 1; i <= len; ++i)
putchar('a' + id);
if(stk.size())
putchar(stk.top()), stk.pop();
}
while(c3--){
for(int i = 1; i <= len + 1; ++i)
putchar('a' + id);
if(stk.size())
putchar(stk.top()), stk.pop();
}
while(c4--){
for(int i = 1; i <= len + 2; ++i)
putchar('a' + id);
if(stk.size())
putchar(stk.top()), stk.pop();
}
if(end){
for(int i = 1; i <= end; ++i)
putchar('a' + id);
}
putchar('\n');
}
inline void solve(){
scanf("%s", s + 1);
n = strlen(s + 1);
for(int i = 0; i < M; ++i)
cnt[i] = 0;
for(int i = 1; i <= n; ++i)
++cnt[s[i] - 'a'];
mx = id = 0;
for(int i = 0; i < M; ++i){
if(cnt[i] > mx){
mx = cnt[i];
id = i;
}
}
if(mx <= n - mx + 1)
solve1();
else
solve2();
}
int main(){
T = read();
while(T--)
solve();
return 0;
}