[题解]CF1822E Making Anti-Palindromes
思路
发现对于无解的情况,当且仅当同一种字符出现次数大于 \(\frac{n}{2}\) 或者 \(n\) 为奇数。
然后统计每一种有字符的冲突对数,记 \(vis_i\) 表示字符 \(i\) 的冲突对数,并记 \(num = \max \{vis_i\}\),\(cnt = \sum vis_i\)。
如果 \(2num \leq cnt\),说明你每一次操作都会使两种不同字符交换到可行的位置,所以答案为 \(\lceil \frac{cnt}{2} \rceil\)。
否则,说明需要将 \(vis_i = num\) 的这一种字符与其它字符交换,答案为 \(num\)。
Code
#include <bits/stdc++.h>
#define re register
using namespace std;
int n;
int vis[50];
string s;
inline int up(int a,int b){
if (a % b == 0) return a / b;
return a / b + 1;
}
inline void solve(){
int Max = 0,ans = 0;
cin >> n >> s;
s = ' ' + s;
if (n & 1){
puts("-1");
return;
}
memset(vis,0,sizeof(vis));
for (re int i = 1;i <= n;i++){
vis[s[i] - 'a']++;
Max = max(Max,vis[s[i] - 'a']);
}
if (Max > n / 2){
puts("-1");
return;
}
memset(vis,0,sizeof(vis));
for (re int i = 1,j = n;i <= j;i++,j--){
if (s[i] == s[j]) vis[s[i] - 'a']++;
}
int cnt = 0,num = 0;
for (re int i = 0;i < 26;i++){
if (vis[i]){
cnt += vis[i];
num = max(num,vis[i]);
}
}
if (num * 2 <= cnt) printf("%d\n",up(cnt,2));
else printf("%d\n",num);
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--) solve();
return 0;
}

浙公网安备 33010602011771号