题意:
思路:
1:我们知道他一定是偶数长度,所以我们把字符串分成两部分s1和s2
len = i-s1.size()
4:我们根据冒泡排序的性质:对于任意两个数看他是否逆序即大数在前小数在后如果逆序则进行交换次数+1,那么我们就可以根据这个性质求出s2到s1通过树状数组或归并排序求逆序对求出步数
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
map<char,int>mp;
queue<int>q[30];
const int N = 1e6 + 10;
int d[N];
int lowbit(int x)
{
return x&(-x);
}
void add(int x)
{
for(;x<= N;x += lowbit(x))
d[x]++;
}
int query(int x)
{
int res = 0;
for(;x;x-=lowbit(x))
res += d[x];
return res;
}
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
for(int i = 0;i < n;i ++)
{
mp[s[i]] ++;
}
for(auto [l,r]:mp)
{
mp[l] = r/2;
}
string s1,s2;
int ans = 0;
for(int i = 0;i < n;i ++)
{
if(mp[s[i]]!=0)
s2+=s[i],mp[s[i]]--,ans += i+1-s2.size();
else
s1 += s[i];
}
for(int i = 0;i < s2.size();i ++)
{
q[s2[i]-'a'].push(i);
}
vector<int>num;
for(int i = 0;i < s1.size();i ++)
{
num.push_back(q[s1[i]-'a'].front());
q[s1[i]-'a'].pop();
}
for(int i = 0;i < num.size();i ++)
{
ans += query(n/2)-query(num[i]+1);
add(num[i]+1);
}
cout << ans << '\n';
}
signed main()
{
solve();
}