给出两个长度相同且由大写英文字母组成的字符串A、B,保证A和B中每种字母出现的次数相同。
现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B。
给出两个长度相同且由大写英文字母组成的字符串A、B,保证A和B中每种字母出现的次数相同。
现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B。
第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度。
第二行和第三行各一个长度为n的字符串,并且只包含大写英文字母。
鸣谢 oimaster
题解:权值树状数组求逆序对。
预处理的时候把第一个字符串顺序编号,然后第二个字符串中的字符找到他在第一个串中的位置,并记录。
最后对第二个串记录下来的序列求逆序对。
#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); }