第十八届浙大城市学院程序设计竞赛 G(思维,对序列的操作)

题目:传送门
参考文章
题意:
给你两个序列a和b(序列由1~n构成,而且序列中每个元素大小都不相同)
现在给你对a序列两种操作:
1、将a序列中的第一个元素删除,在a序列尾部追加任意一个数字;
2、将a序列中的任何一个元素改为任意一个数字;
问最少操作多少次才能将a序列变为b序列。

思路+代码:

/*
执行k次1操作相当于将(k+1~n)的数字向前移动k位,最后k位自动匹配;
我们记录数组a向前移动k位就和数组b上的数字匹配的数字的个数cnt = mp[k],只要找到最大的一组cntMax = (mp[k],k∈(0,n-1))就能让最后的操作次数ans最小,
ans = n - mp[k];
这里解释以下ans,已知:操作1次数为k,操作2的次数为n-k-mp[k](因为最后面的k个自动匹配了,然后还有mp[k]个在操作1后也匹配了,所以还未匹配的就是n-k-mp[k]个);
所以ans = min(ans,n - mp[k]);
*/
#include <iostream>
#include <map>
using namespace std;
const int N = 1e6+10;
int a[N],b[N],n;
map <int,int> mp;
int main(void)
{
    //要加上这句话,不然就TLE了
    ios_base::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++){ int x; cin>>x; a[x] = i; }
    for(int i=1;i<=n;i++){ int x; cin>>x; b[x] = i; }
    for(int i=1;i<=n;i++){
        mp[ a[i] - b[i] ]++;
    }
    //这里解释以下为什么ans一开始是n-1,因为a,b序列都是由1~n构成的,最坏的情况就是有一个匹配,此时mp[k] = 1,ans = n - mp[k] = 1;
    int ans = n-1;
    for(int i=0;i<=n-1;i++){
        ans = min(ans,n - mp[i]);
    }
    cout<<ans<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值