牛客练习赛54 C.排序 暴力枚举+逆序对

Posted kaka0010

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客练习赛54 C.排序 暴力枚举+逆序对相关的知识,希望对你有一定的参考价值。

原题链接: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();
}


以上是关于牛客练习赛54 C.排序 暴力枚举+逆序对的主要内容,如果未能解决你的问题,请参考以下文章

牛客网NowCoder 2018年全国多校算法寒假训练营练习比赛(第四场)A.石油采集(dfs) B.道路建设(最小生成树prim) C.求交集(暴力) F.Call to your teacher

牛客网Nowcoder 牛客练习赛13 A.幸运数字Ⅰ B.幸运数字Ⅱ(数组或者dfs) C.幸运数字Ⅲ(思维)

牛客练习赛7E珂朵莉的数列

牛客练习赛83 C.集合操作(二分,单调性)

牛客练习赛52 C.烹饪 DP + gcd性质

逆序对的三种解法