题意:
将一个字符串只能通过相邻字符交换从而反转,问需要多少次数
思路:
我们从末尾开始,往前把字符交换,如果字符串里没有重复字母的话,这样就是最优秀的 , 相邻交换,求逆序对即可 ,但对于有重复字母,我们需要肯定将较前的字母先往前把字符交换,这样次数一定会更少,所有从后往前遍历,记录下标,这样保证前面的字符会首先取得,用栈也可以,然后选择好位置用树状数组求逆序对即可
#include <bits/stdc++.h>
using namespace std;
const int N = 200000 + 50;
#define LL long long
LL c[N];
char s[N];
int a[N] , n;
int lowbit(int x){
return x & (-x);
}
void update(int x,int k){
for(;x <= n;x += lowbit(x)){
c[x] += k;
}
}
int query(int x){
int res = 0;
for(;x;x -= lowbit(x)){
res += c[x];
}
return res;
}
vector <int> v[28];
int main(){
scanf("%d",&n);
scanf("%s",s + 1);
for(int i = n;i >= 1;i --){
v[s[i] ^ 97].push_back(n - i + 1);
}
for(int i = n;i >= 1;i --){
a[i] = v[s[i] ^ 97].back();// ^97相当于 - ‘0’
v[s[i] ^ 97].pop_back();
}
LL res = 0;
for(int i = 1;i <= n;i ++){
update(a[i],1);
res += i - query(a[i]);
}
cout << res << '\n';
return 0;
}