E. String Reversal
Posted goto_1600
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E. String Reversal相关的知识,希望对你有一定的参考价值。
题意:
给定一个字符串,你每次可以交换相邻位置的字母,问最少操作多少次才能达到他的反转串
思路:
先把反转串获得,“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;
}
以上是关于E. String Reversal的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round 96 (Rated for Div. 2)E. String Reversal(树状数组求逆序对)
CodeForces - 1430E String Reversal(线段树+模拟)