如果你需要移动一样东西,显然接触或者使用磁场电场之类的可以解决。但是有没有办法进行超越距离的随心所欲的移动?
对于物体或者文字进行超距离移动一直是人类的梦想,有一天这个难题终于被我们的大牛解决了!他现在需要的就是整理数列。数列就是所谓的写在纸上或者在电脑品目上的数列…
整理数列需要一个叫做swap的操作,swap操作就是指大牛通过超距离的控制把数列中的某一位直接插入某两位的中间或者数列的开始或者终止的操作。这个操作的关键在于超距离控制,显然这种事情不能干太多次,不但降RP,而且很耗体力。你的任务就是从初始状态到目标状态所需要做swap的最少次数。
三行,第一行一个整数 n(n<600000)
第二行,n 个整数(1-n),表示初始数列。
第三行,n 个整数(1-n),表示目标数列。
保证整数不重复。
很容易想到,要是交换次数最少,求出两个序列的最长公共子序列,然后用n减去最长的公共子序列长度就是最优的结果,数据范围为5e6,直接求LCS会超时,所以需要优化
根据题目的条件,所有数字在1-n且无重复,可以把问题又LCS转化为LIS,需要构造一个新的数列
假设A数列=[5,4,1,3,2]不管其大小,将其定义为A=[a,b,c,d,e];
然后假设B=[1 2 3 4 5],将其对应为abcde是B=[c,e,d,b,a];
对于A中的定义,abcde是一个单调递增的序列,可以发现只要在B中出现单调递增的序列一定是A的子序列,所以将问题转化为求B数列的最长单调递增子序列,然后把上述的abcde换成下表12345,构造一个新的数列即可求LIS即可
时间复杂度O(N*logN)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e6+7;
const int mod = 998244353;
typedef long long ll;
int inf=0x3f3f3f3f;
const int maxn = 600007;
int h[maxn], a[maxn], dp[maxn];
int main()
{
int n,x;
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
{
scanf("%d", &x);
h[x] = i;
}
for(int i = 1; i <= n; ++i)
{
scanf("%d", &x);
a[i] = h[x];
}
int len = 1;
dp[1] = a[1];
for(int i=2;i<=n;i++)
{
if(a[i]>dp[len])
dp[++len] = a[i];
else
dp[lower_bound(dp+1, dp+1+len, a[i]) - dp] = a[i];
}
cout<<n-len<<endl;
return 0;
}