bzoj 2789: [Poi2012]Letters

2789: [Poi2012]Letters

Time Limit: 20 Sec   Memory Limit: 128 MB
Submit: 297   Solved: 197
[ Submit][ Status][ Discuss]

Description

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

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


Input


第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度。

第二行和第三行各一个长度为n的字符串,并且只包含大写英文字母。



Output

一个非负整数,表示最少的交换次数。

Sample Input

3
ABC
BCA

Sample Output

2

HINT

 



ABC -> BAC -> BCA

Source

鸣谢 oimaster

[ Submit][ Status][ Discuss]

题解:权值树状数组求逆序对。

预处理的时候把第一个字符串顺序编号,然后第二个字符串中的字符找到他在第一个串中的位置,并记录。

最后对第二个串记录下来的序列求逆序对。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define N 1000003
using namespace std;
int n,ch[30][100000],len[N],pd[30];
long long tr[N],ans;
char s[N],s1[N];
int lowbit(int x)
{
	return x&(-x);
}
void change(int x,long long v)
{
	for (int i=x;i<=n;i+=lowbit(i))
	 tr[i]+=v;
}
long long  sum(int x)
{
	int ans=0;
	for (int i=x;i;i-=lowbit(i))
	 ans+=tr[i];
	return ans;
}
int main()
{
	scanf("%d\n",&n);
	scanf("%s",s+1);
	scanf("%s",s1+1);
	for (int i=1;i<=n;i++)
	 {
	 	int x=s[i]-'A';
	 	ch[x][++ch[x][0]]=i;
	 }
	for (int i=1;i<=n;i++)
	 {
	 	int x=s1[i]-'A';
	 	pd[x]++;
	 	len[i]=ch[x][pd[x]];
	 }
	for (int i=n;i>=1;i--)
	 {
	 	ans+=sum(len[i]);
	 	change(len[i],1);
	 }
	printf("%lld\n",ans);
}



你可能感兴趣的:(bzoj 2789: [Poi2012]Letters)