Codeforces Round #723 (Div. 2) D. Kill Anton(樹狀陣列)
阿新 • • 發佈:2021-07-29
目錄
Description
給出一個字串 s,每次可以交換兩個相鄰的字元,要構造一個合法的字串 t,使得 t 變為 s 所需要的操作次數最多
Input
4
ANTON
NAAN
AAAAAA
OAANTTON
Output
NNOTA
AANN
AAAAAA
TNNTAOOA
Solution
前置結論,操作次數最多的時候一定是相同的字母連線在一起的時候,比如: AAANNNOOTTT 至於結論的正確性,我想這應該是逆序對的特性; 有了結論之後,接下來只要列舉 ANOT,ANTO....等 24 種組合找到逆序對最多的字串就可以了;
Code
const int N = 1e5 + 5; ll n, m, _; int i, j, k; int a[N]; string t = "ANOT"; int bit[4]; int c[N], b[N]; map<char, vector<int>> mp; void clear() { mp.clear(); bit[0] = bit[1] = bit[2] = bit[3] =0; rep(i, 0, n) c[i] = 0; t = "ANOT"; } void add(int x) { for(; x <= n; x += lowbit(x)){ c[x] ++; } } int ask(int x) { int ans = 0; for(; x; x -= lowbit(x)){ ans += c[x]; } return ans; } int idx(char ch) { if(ch == 'A') return 0; if(ch == 'N') return 1; if(ch == 'O') return 2; if(ch == 'T') return 3; } string work(string s) { string ans = ""; rep(i, 0, 3){ int x = idx(t[i]); rep(j, 1, bit[x]) ans += t[i]; } return ans; } void init(string s) { for(int i = 0; s[i]; i ++){ mp[s[i]].pb(i + 1); } rep(i, 0, n) c[i] = 0; } ll go(string s) { int sz = s.size(); for(int i = sz - 1; i >= 0; i--){ b[i + 1] = *mp[s[i]].rbegin(); mp[s[i]].pop_back(); //dbg(b[i + 1]); } ll ans = 0; per(i, 1, sz){ ans += ask(b[i]); add(b[i]); } return ans; } signed main() { IOS; rush(){ string str, s, ans; cin >> str; n = str.size(); for(int i = 0; str[i]; i++){ int x = idx(str[i]); bit[x] ++; } ll maxx = 0; do{ init(str); s = work(str); ll tmp = go(s); if(tmp >= maxx){ maxx = tmp; ans = s; } }while(next_permutation(t.begin(), t.end())); ps(ans.c_str()); clear(); } return 0; }