https://codeforces.com/problemset/problem/600/C
题意翻译
给出一个由小写字母组成的字符串 ss。首先你可以改变 ss 中任意多个字母。然后你可以改变 ss 中各个字母的排列顺序。问如果要将 ss 变成回文串至少要改变多少个字母?(改变排列顺序不算改变字母)
输入输出样例
输入 #1复制
aabc
输出 #1复制
abba
输入 #2复制
aabcd
输出 #2复制
abcba
思路:假如有t个奇数个数的部分,那么能凑成回文串的变化次数最小是t/2下取整。比如奇 奇 奇 奇,互相给一个就能变成回文。
比如奇 奇 奇 剩下一个奇数不用动。所以整个是t/2下取整。
然后贪心,肯定是把字典序大的字符变成小的最划算,双指针模拟一下找到两个奇数的一小一大互相换。
最后输出就好了。
第一次碰到map的倒序遍历要用新的迭代器,还要rbegin(),rend()
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5;
typedef long long LL;
map<LL,LL>map1;
map<LL,LL>:: iterator it;
map<LL,LL>:: reverse_iterator rit;//倒序遍历的时候注意
int main(void)
{
string a,b;b="#";
cin>>a;LL len=a.length();
b+=a;
for(LL i=1;i<=len;i++){
map1[b[i]-'a']++;
}
LL i=0;LL j=25;
while(i<j)
{
while(i<j&&!(map1[i]&1)) i++;
while(i<j&&!(map1[j]&1)) j--;
map1[i]++;map1[j]--;
}
for(it=map1.begin();it!=map1.end();it++){
for(LL i=1;i<=(it->second)/2;i++){
cout<<char(it->first+'a');
}
}
for(it=map1.begin();it!=map1.end();it++){
if((it->second)&1) cout<<char(it->first+'a');
}
for(rit=map1.rbegin();rit!=map1.rend();rit++){
for(LL i=1;i<=(rit->second)/2;i++){
cout<<char(rit->first+'a');
}
}
cout<<endl;
return 0;
}