TP
考虑转化一下这个题,最小交换次数本质上就是新的序列的逆序对的个数,我们给每个位置上编上号
1
−
n
1-n
1−n,然后随机打乱序列,使得他的(升序排序下)逆序对最多
t
h
e
f
i
r
s
t
the\ first
the first
当两个相同字符的编号排成新的序列时,小编号的在新序列一定在大编号的左边
这不是我们不愿意增加逆序对,是求的那个人求最小交换次数时一定会这样子去看(这样交换次数一定会少至少1),设给的为
p
i
,
p
j
p_i,p_j
pi,pj且
p
i
<
p
j
p_i<p_j
pi<pj
如果交换
证明:因为
p
i
<
p
j
p_i<p_j
pi<pj,所以以
i
i
i位置开头的逆序对依旧存在,以
j
j
j位置结尾的逆序对依旧存在
然后中间的分类讨论即可得证
这里有一个结论:一定存在一种逆序对最多的方案,满足同种碱基都相邻。
证明:我们用调整法,假设序列中有这么一段两边都有个
A
A
A(省略号中间没有
A
A
A):
A
.
.
.
.
.
.
A
A......A
A......A,前面一个的初始位置为
i
i
i,后面一个的初始位置为
j
j
j,此时
i
<
j
i < j
i<j 。令省略号中间比
i
i
i 小的数量为
a
a
a ,比
j
j
j 大的数量为
b
b
b。如果
a
≥
b
a\geq b
a≥b,把右边的
A
A
A 移到省略号左边,逆序对的变化量为
a
b
≥
0
ab\geq0
ab≥0 。如果
a
<
b
a<b
a<b ,把左边的
A
A
A 移到省略号右边,逆序对的变化量为
b
−
a
>
0
b-a>0
b−a>0。两种使
A
A
A 相邻的方法总有一个不会让逆序对数减小,得证。
代码去网上找找吧,总会有的
#include <bits/stdc++.h>
#define lowbit(x) (x&(-x))
using namespace std;
typedef long long LL;
const int maxn = 1e5+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int n;
int bit[maxn];
char s[maxn];
vector<int> vec[4];
bool vis[4];
int now[10],a[maxn];
LL maxx,maxx_now[5];
/*bit Tree*/
void add(int x){
for(int i=x;i<=n;i+=lowbit(i))
bit[i]++;
}
LL query(int x){
LL ans=0;
for(int i=x-1;i;i-=lowbit(i))
ans+=bit[i];
return ans;
}
void check(){
int ind=0;
for(int i=1;i<=n;i++)
bit[i]=0;
for(int i=1;i<=4;i++){
for(auto t:vec[now[i]])
a[++ind]=t;
}
LL ans=0;
for(int i=n;i>=1;i--){
ans+=1ll*query(a[i]);
add(a[i]);
}
if(ans>maxx){
maxx=ans;
for(int i=1;i<=4;i++)
maxx_now[i]=now[i];
}
}
void dfs(int x){
if(x==5){
check();
return;
}
for(int i=0;i<=3;i++){
if(vis[i])
continue;
now[x]=i;
vis[i]=1;
dfs(x+1);
vis[i]=0;
}
}
int main (){
int t=readint();
while(t--){
maxx=-1;
memset(now,0,sizeof(now));
memset(maxx_now,0,sizeof(maxx_now));
memset(vis,0,sizeof(vis));
scanf("%s",s+1);
n=strlen(s+1);
for(int i=0;i<=3;i++)
vec[i].clear();
for(int i=1;i<=n;i++){
if(s[i]=='A')
vec[0].emplace_back(i);
else if(s[i]=='N')
vec[1].emplace_back(i);
else if(s[i]=='O')
vec[2].emplace_back(i);
else
vec[3].emplace_back(i);
}
dfs(1);
for(int i=1;i<=4;i++){
if(maxx_now[i]==0)
for(int j=0;j<vec[0].size();j++)
printf("A");
else if(maxx_now[i]==1)
for(int j=0;j<vec[1].size();j++)
printf("N");
else if(maxx_now[i]==2)
for(int j=0;j<vec[2].size();j++)
printf("O");
else
for(int j=0;j<vec[3].size();j++)
printf("T");
}
puts("");
}
return 0;
}