题意:原题很清楚了.
解题报告:
考虑暴力dp
dp[p][q]
表示第一只手在p另一只手在q的最短时间
1.若a[p]==b[q] 则
dp[p][q]=min(dp[p−1][q],dp[p][q−1])+1
2.若a[p]!=b[q] 则
dp[p][q]=min(dp[p−1][q−1])+t−1
注意到第二种转移中其实是找到从
p
,
这个可以预处理,要找的时候二分查找
但是空间仍然不对,其实可以只记录dp[p]即第一个指针在
p
<script type="math/tex" id="MathJax-Element-7">p</script>的时候的最短时间,因为只有在数字相同的时候才会转移
打成记忆化会十分直观
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define N 1000005
using namespace std;
vector<int>del[N<<1];
int n,dp[N],a[N],b[N],pos[N];
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
int a=0;char f=1,c=nc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
while(c>='0'&&c<='9'){a=a*10+c-'0';c=nc();}
return a*f;
}
int dfs(int p,int q){
if(!p||!q) return p+q;
if(a[p]==b[q]){
if(dp[p]!=-1) return dp[p];
return dp[p]=min(dfs(p-1,q),dfs(p,q-1))+1;
}
else{
int to=lower_bound(del[p-q+n].begin(),del[p-q+n].end(),p)-(del[p-q+n].begin()+1);
if(to<0) return max(p,q);
else{
int tmp=p-del[p-q+n][to];
return tmp+dfs(p-tmp,q-tmp);
}
}
}
int main(){
memset(dp,-1,sizeof(dp));
n=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=n;++i) b[i]=read(),pos[b[i]]=i;
for(int i=1;i<=n;++i){
int tmp=i-pos[a[i]]+n;
del[tmp].push_back(i);
}
printf("%d\n",dfs(n,n));
return 0;
}