「BZOJ2789」letters
Description
给出两个长度相同且由大写英文字母组成的字符串A、B,保证A和B中每种字母出现的次数相同。
现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B。
Input
第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度。
第二行和第三行各一个长度为n的字符串,并且只包含大写英文字母。
Output
一个非负整数,表示最少的交换次数。
Sample Input
3
ABC
BCA
ABC
BCA
Sample Output
2
HINT
ABC -> BAC -> BCA
题解
cxjyxxw_me:
这题一定对于某个字母
一定是贪心的把离它最近的字母移过来
这样就可以对A串标出1~n的排列的一个序
对这个序求逆序对数即为ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<algorithm> #include<queue> #include<cmath> #include<map> #include<queue> #define ll long long #define inf 2000000000 #define mod 1000000007 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ll ans; int n; char a[1000005],b[1000005]; int val[1000005],t[1000005]; queue<int> q[30]; void add(int x,int val) { for(int i=x;i<=n;i+=i&(-i)) t[i]+=val; } int query(int x) { int sum=0; for(int i=x;i;i-=i&(-i)) sum+=t[i]; return sum; } int main() { n=read(); scanf("%s",a+1);scanf("%s",b+1); for(int i=1;i<=n;i++) q[a[i]-'A'].push(i); for(int i=1;i<=n;i++) { val[i]=q[b[i]-'A'].front(); q[b[i]-'A'].pop(); } //for(int i=1;i<=n;i++)cout<<val[i]; for(int i=1;i<=n;i++) { ans+=query(n)-query(val[i]); add(val[i],1); } printf("%lld\n",ans); return 0; } |
Subscribe