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; }




posted @ 2021-06-01 11:41  xiaodangao  阅读(152)  评论(0编辑  收藏  举报