D. Kill Anton(Codeforces Round #723 (Div. 2)题解)
题目链接:D. Kill Anton
思路:先考虑他会怎么做才能最少次数还原串。我们发现对于一个串b若将它还原成串a,最好是每一次交换,都减少一个逆序对数量,这里的逆序对数量是以a为中心来说的。这显然是最优解,因为当b相对于a的逆序对数量减为0时,b=a。而且他的交换方式是相邻两个字符间进行交换,所以每一次交换最多减少一个逆序对数量。那我们考虑如何才能产生最多的逆序对的数量,首先我们先看一下只有两个字符的情况:
\((A_1)NNNN(A_2)NN(A_3)N\)
为了方便,将A每一个都标上了序号,我们发现\(A_1\)一直移动到\(A_2\)的位置,都在不断地产生逆序对,如果\(A_1\)再向后移动,那么当前移动的就不是\(A_1\)了,那我们可以看成是\(A_2\)移动,\(A_1\)停在原来\(A_2\)的位置,那么显然,\(A_1\)停在原来\(A_2\)的位置就绝对不是最优解,只有\(A_1\),\(A_2\),\(A_3\)都移动到最后面,才产生最大的逆序对数,所以我们发现,最优解构造有一种情况一定是把相同字符都放在一起,所以我们的做法就很好做了,这里我们只考虑两个字符,因为在考虑两个字符时,即使插入任意别的字符在任意的位置,也对于当前字符排列的逆序对没有什么影响。然后我们暴力枚举字符对,算出每一种字符对的贡献,最后利用全排列函数来求解最优解。
\(Code:\)
#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#define ch() getchar()
#define pc(x) putchar(x)
#include<stack>
#include<unordered_map>
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) x&(-x)
#define ll long long
#define ull unsigned long long
#define pb emplace_back
#define mp make_pair
#define PI acos(-1)
using namespace std;
template<typename T>void read(T&x){
static char c;
static int f;
for(c=ch(),f=1; c<'0'||c>'9'; c=ch())if(c=='-')f=-f;
for(x=0; c>='0'&&c<='9'; c=ch())x=x*10+(c&15);
x*=f;
}
template<typename T>void write(T x){
static char q[65];
int cnt=0;
if(x<0)pc('-'),x=-x;
q[++cnt]=x%10,x/=10;
while(x)
q[++cnt]=x%10,x/=10;
while(cnt)pc(q[cnt--]+'0');
}
const int N = 1e2+10;
int _;
string a,tmp = "ANTO",s = "ANTO";
//int id[N]
bool st[100010];
vector<int>G[N];int id[N][N];
ll cnt[N][N];
void iniv(){
for(auto p:tmp)for(auto k:tmp)cnt[p-'A'][k-'A'] = 0;
}
int cnts[N];
ll work(string s){
ll ans = 0;
rep(i,0,3){
rep(j,i+1,3){
ans += cnt[s[i]-'A'][s[j]-'A'];
}
}
return ans;
}
void solve(){
ios::sync_with_stdio(false);
cin>>_;
while(_--){
iniv();
string b = "";
cin>>a;
memset(cnts,0,sizeof cnts);
for(auto p:a){
cnts[p-'A']++;
}
//iniv();
rep(i,0,3){
rep(j,i+1,3){
//if(p == k)continue;
ll l = 0,r = 0, ansl = 0,ansr = 0;
rep(p,0,(int)a.size()-1)if(a[p] == tmp[i])l++;else if(a[p] == tmp[j])ansl += l;
bep(p,(int)a.size()-1,0)if(a[p] == tmp[i])r++;else if(a[p] == tmp[j])ansr += r;
cnt[tmp[j]-'A'][tmp[i]-'A'] = ansl;
cnt[tmp[i]-'A'][tmp[j]-'A'] = ansr;
}
}
sort(s.begin(),s.end());
ll mx = -1;//
do{
ll now = work(s);
if(now>mx)b = s,mx = now;
// cout<<s<<':'<<now<<endl;
}while(next_permutation(s.begin(),s.end()));
for(auto p:b){
rep(i,1,cnts[p-'A'])cout<<p;
}
cout<<endl;
}
}
signed main(){solve();return 0; }