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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具