您的位置:首页 > 其它

bzoj 2789: [Poi2012]Letters

2016-05-03 09:09 441 查看

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

[align=left][/align]

第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度。
第二行和第三行各一个长度为n的字符串,并且只包含大写英文字母。

Output

[align=left]一个非负整数,表示最少的交换次数。[/align]

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
,pd[30];
long long tr
,ans;
char s
,s1
;
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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: