CF1430E String Reversal

可以想到一个结论:(不会证

在原字符串中的相同字符,经过操作后相对位置不变

思路

我们可以给 'a'-'z' 每个字符开个数组,

它们各自在目标字符串中的出现位置存到一个“桶”里。

然后再把这个“桶”对应到原字符串里,就会得到一个数组。

比如说,aabcba 这个字符串,它的目标字符串就是 abcbaa

存每个字母在目标字符串中的位置:

a: 1, 5, 6
b: 2, 4
c: 3

然后再把每个字母从“桶”里取出来,对应到原字符串 abcbaa

a: 1
a: 5
b: 2
c: 3
b: 4
a: 6

我们只需要计算,这个数组相邻交换几次可以变成排好序的 1-n

也就是这个数组的逆序对(这里是三个,也就是交换三次)。

代码

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <utility>
#include <algorithm>
#define int long long
using namespace std;
int c[200050], rk[200050], vis[30], ap[30][200050], n, ans;string s, t;pair<int, int> a[200050];
int lbt(int x) {return x & -x;}
void chg(int x, int k)
{
    for(int i = x;i <= n;i += lbt(i))
        c[i] += k;
}
int ask(int x)
{
    int ret = 0;
    for(int i = x;i;i -= lbt(i))
        ret += c[i];
    return ret;
}
signed main()
{
    cin >> n >> s;t = s;reverse(t.begin(), t.end());
    n = s.length();s = ' ' + s;t = ' ' + t;
    for(int i = 1;i <= n;++i)
        ap[t[i] - 'a'][vis[t[i] - 'a']++] = i;
    memset(vis, 0, sizeof vis);
    for(int i = 1;i <= n;++i)
        a[i].first = ap[s[i] - 'a'][vis[s[i] - 'a']++], a[i].second = i;
    sort(a + 1, a + n + 1);
    for(int i = 1;i <= n;++i)
        rk[a[i].second] = i;
    for(int i = n;i >= 1;--i)
    {
        chg(rk[i], 1);
        ans += ask(rk[i] - 1);
    }
    cout << ans << endl;
    return 0;
}
posted @   Jijidawang  阅读(2)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示