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

该博客探讨了一种字符串处理问题,其中目标是通过最少的字符交换次数将ATGC四种字符组成的字符串中相同字符归类在一起。博主分析了问题本质与交换排序的联系,指出逆序对数量与所需的交换次数相同。为解决此问题,博主采用了全排列枚举的方法,计算每种字符优先级排列下的逆序对数,并记录最小值作为答案。代码中使用了BIT(Binary Indexed Tree)数据结构来高效计算逆序对。
摘要由CSDN通过智能技术生成

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


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值