#树状数组#洛谷 3531 [POI2012] LIT-Letters

题目

给出两个长度相同且由大写英文字母组成的字符串\(A\)\(B\),保证\(A\)\(B\)中每种字母出现的次数相同。

现在每次可以交换\(A\)中相邻两个字符,求最少需要交换多少次可以使得\(A\)变成\(B\)


分析

举个例子\(dabac\)要变成\(bcada\)

首先,相同字母的先后顺序不会改变,如果改变顺序肯定会使答案不优,那么可以用26个队列装入每个字母在\(A\)串中的顺序,然后用\(B\)串为基准离散化,然后以上面为例就是

队列\(a:2,4;b:3;c:5;d:1\)

然后对应回\(B\)串形成数列\(35214\)

然后可以发现这里面的每个数应该排在相应的位置

那不就是逆序对吗?

树状数组求解!


代码

#include <cstdio>
#include <cctype>
#include <queue>
#define rr register
using namespace std;
const int N=1000011; queue<int>q[27]; int n,b[N],a[N]; long long ans;
inline void add(int x){for (;x<=n;x+=-x&x) ++b[x];}
inline signed query(int x){rr int ans=0; for (;x;x-=-x&x) ans+=b[x]; return ans;}
signed main(){
	scanf("%d",&n);
	for (rr int i=1;i<=n;++i){
		rr char c=getchar();
		while (!isalpha(c)) c=getchar();
	    q[c^64].push(i);
	}
	for (rr int i=1;i<=n;++i){
		rr char c=getchar();
		while (!isalpha(c)) c=getchar();
		a[i]=q[c^64].front(); q[c^64].pop();		
	}
	for (rr int i=n;i;--i) ans+=query(a[i]-1),add(a[i]);
	return !printf("%lld",ans); 
}
posted @ 2020-01-15 20:06  lemondinosaur  阅读(88)  评论(0编辑  收藏  举报