#树状数组#洛谷 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); 
}

猜你喜欢

转载自www.cnblogs.com/Spare-No-Effort/p/12198548.html