原题链接:https://ac.nowcoder.com/acm/contest/1842/C
题意
有ATGC四种字符组成的字符串,每次可以交换相邻的一对,问最少多少次可以将同种字符分到一起
分析
每次交换相邻字符,不就是交换排序的基本操作吗?又有一个性质,交换排序次数和逆序对个数是相同的,因此我们只要算逆序对个数就可以了。然后就是给字符排一下优先级,一共也就24种全排列,全部暴力枚举一下就可以了,复杂度是O(24n)。
Code
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define re register
typedef long long ll;
typedef pair<ll, ll> PII;
typedef unsigned long long ull;
const int N = 5e5 + 10, M = 1e6 + 5, INF = 0x3f3f3f3f;
const int MOD = 998244353;
char mp[4] = {'A', 'T', 'G', 'C'};
struct BIT {
ll c[N];
int lowbit(int x) {return x&-x;}
void add(int x, int val) {for (int i = x; i < N; i += lowbit(i)) c[i] += val;}
ll query(int x) {ll ans = 0; for (int i = x; i > 0; i -= lowbit(i)) ans += c[i]; return ans;}
}bit;
int a[N];
void solve() {
string s; cin >> s;
ll ans = 1e18;
int n = s.size();
for (int i = 0; i < 24; i++) {
next_permutation(mp, mp+4);
for (int j = 0; j < n; j++) {
for (int k = 0; k < 4; k++) {
if (s[j] == mp[k]) a[j] = k + 1;
}
}
memset(bit.c, 0, sizeof bit.c);
ll res = 0;
for (int j = 0; j < n; j++) {
res += bit.query(n) - bit.query(a[j]);
bit.add(a[j], 1);
}
ans = min(ans, res);
}
cout << ans << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}