题意
给你一个字符串,每次你能交换两个相邻的字符,问要把这个字符串变的和原来相反,最少需要多少次操作。
解题思路:
相同的字符的相对位置在交换后不变一定最优,接下来想到冒泡排序,我们每次完成最后一个字符,记录下这个字符在原数组中最后次出现的位置,需要的操作次数就是他们的位置相减,这个字符完成后,原数组在它后面的字符的位置已经都向前移动了一位,我用了树状数组维护,然后只要每次完成最后一个字符就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+5;
const int mod = 1e9+7;
long long a[maxn],n;
void update(int k,int val)
{
for(int i=k;i<=n;i+=(i&-i))
a[i]+=val;
}
long long query(int k)
{
int ans=0;
for(int i=k;i;i-=(i&-i))
ans+=a[i];
return ans;
}
int main(){
string s;
cin>>n>>s;
s=" "+s;
for(int i=1;i<=n;i++)
update(i,1);
stack<int> st[30];
for(int i=1;i<=n;i++)
st[s[i]-'a'].push(i);
long long ans=0;
for(int i=1;i<=n;i++)
{
int x = st[s[i]-'a'].top();
st[s[i]-'a'].pop();
int xx=query(x);
update(x,-1);
ans+=(i-xx);
}
cout<<ans<<endl;
return 0;
}