题意:
给定一个字符串,你每次可以交换相邻位置的字母,问最少操作多少次才能达到他的反转串
思路:
先把反转串获得,“abcbd"的反转串"dbcba”,然后我们从反转串的最前面开始遍历,由于贪心,我们尽量把在原串中最近出现该字母的位置放到位置上,第一步模拟出来就是"dabcb",对于d后面这些位置也就是消除了影响,模拟下来每一次放到前面的贡献就是现在还在序列中并且在这个位置前并且未被操作的字母的个数,那么用个树状数组维护一下就行了,复杂度O(nlogn)。
代码:
// Problem: E. String Reversal
// Contest: Codeforces - Educational Codeforces Round 96 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1430/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define IL inline
#define x first
#define y second
typedef long long ll;
using namespace std;
const int N=200010;
int tr[N];
int n;
int lowbit(int x)
{
return x&-x;
}
int query(int x)
{
int res = 0;
for(int i=x;i;i-=lowbit(i))
res+=tr[i];
return res;
}
void add(int x,int d)
{
for(int i=x;i<=n;i+=lowbit(i))
tr[i]+=d;
}
queue<int>q[26];
int main()
{
cin>>n;
string s;
cin>>s;
ll res=0;
s=" "+s;
for(int i=1;i<s.size();i++)
{
q[s[i]-'a'].push(i);
add(i,1); }
for(int i=(int)s.size()-1;i>=1;i--)
{
int tt=q[s[i]-'a'].front();
q[s[i]-'a'].pop();
res+=query(tt-1);
add(tt,-1);
}
cout<<res<<endl;
return 0;
}