【2019国庆集训day2-s】秘密邮件

\(Description\)

\(Smart\)收到了一封来自外星球的秘密邮件。邮件由\(n\)个大写英文字母组成,不巧的是\(Smart\)收到邮件以后一不小心打乱了原来的字母顺序。但是聪明的\(Smart\)记住了原邮件的完整内容,现在他每次可以选择打乱后的邮件中相邻的两个字母进行交换,问最少交换多少次能够将打乱的邮件恢复成原邮件。

\(Input\)

第一行\(1\)个整数\(n\)代表邮件长度。

第二行长度为\(n\)的只包含大写字母的字符串表示打乱后的邮件。

第三行长度为\(n\)的只包含大写字母的字符串表示原邮件。

为了保证打乱后的邮件可以恢复成原邮件,所有测试数据满足任意一种大写字母在两封邮件中的出现次数相同。

\(Output\)

输出一个整数表示最少的交换次数。

\(Sample Input 1\)

4
ABCD
DBCA

\(Sample Output 1\)

5

\(Hint\)

【数据范围】

\(40%\)的数据\(:n≤30\)

另外\(20%\)的数据\(:n=5000;\)

\(100%\)的数据\(:n≤1000000\)

\(Solution\)

很明显的逆序对......
把打乱的邮件中的大写字母一一编号,然后把它们映射到原邮件。
这里我们会遇到相同的大写字母出现多次,那么我们考虑将大写字母出现较早的先映射

就像样例一样

\(ABCD\)
\(DBCA\)

\(1 2 3 4\)
映射后就是
\(4 2 3 1\)
然后答案就是求\(4 2 3 1\)这个序列的逆序对个数
\((4,2)\) \((4,3)\) \((4,1)\) \((2,1)\) \((3,1)\)

求逆序对的个数可以用树状数组\(or\)归并排序......
这里用的是归并排序

#include<bits/stdc++.h>
#define Re register int
using namespace std;
vector<long long> W[27];
long long N,a[1000050],b[1000050],Now[27];
long long Ans;
char S_Mess[1000050],S_Last[1000050];
inline void merge_sort(int l,int r){
    if(r-l>0){
        int mid=(l+r)>>1;
        int Wh=l;
        int p=l,q=mid+1;
        merge_sort(l,mid);
        merge_sort(mid+1,r);
        while(p<=mid || q<=r){
            if(q>r || (p<=mid && a[p]<=a[q])) b[Wh++]=a[p++];
            else{
                b[Wh++]=a[q++];
                Ans+=mid-p+1;
            }
        }
        for(Re i=l; i<=r; i++) a[i]=b[i];
    }
}
int main(){
    scanf("%d",&N);
    scanf("%s",S_Mess+1);
        scanf("%s",S_Last+1);
    for (Re i=1; i<=N; ++i) W[S_Last[i]-'A'+1].push_back(i);
    for (Re i=1; i<=N; ++i) a[i]=W[S_Mess[i]-'A'+1][Now[S_Mess[i]-'A'+1]++];
    merge_sort(1,N);
    printf("%lld",Ans);
    return 0;
}

转载于:https://www.cnblogs.com/to-the-end/p/11617800.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值