题目大意:给你一个长度为 n n n的字符串,你每次可以选择相邻的两个字符进行交换,求最小的交换次数,使得进行若干次交换后字符串变为原字符串的倒序.
解题思路:对于原串中的一个字符如果它不等于目标串位置的字符,那么它就需要跟原串中其他位置的目标字符进行交换,最优策略就是选择离当前位置最近的字符来进行交换,然后不断地模拟这个过程.用树状数组模拟,每个元素回到自己的位置取决于它前面有多少个元素,然后动态的去更新.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define syncfalse ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N = 2e5+5;
char s[N];
int n;
const int MAX = 2e5+5;
int tree[MAX];
inline int lowbit(int x){
return x & (-x);
}
inline void update(int i, int x){
for (int pos = i; pos <= n; pos+=lowbit(pos))
tree[pos]+=x;
}
inline int query(int n){ //区间[1, n]的查询
int ans = 0;
for (int pos = n; pos; pos-=lowbit(pos))
ans += tree[pos];
return ans;
}
queue<int>id[30];
int main(){
syncfalse
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
cin>>n;
cin>>s+1;
for (int i = 1; i <= n; ++i){
id[s[i]-'a'].push(i);
update(i, 1);
}
ll ans = 0;
for (int i = n; i >= 1; --i){
int index = id[s[i]-'a'].front();id[s[i]-'a'].pop();
ans+=query(index)-1;
update(index, -1);
}
cout << ans << "\n";
return 0;
}