题目:传送门
参考文章
题意:
给你两个序列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;
}