文章目录
Part1:题目链接
Part2:题目
Part3:思路
突然高产,实则心无波澜,甚至还能再更一篇出来。
如果只看题目的话,这道题就是1000%的LCS(Longest Common Sequence,最长公共子序列)。
题目中50%的数据是可以通过LCS( O(n^2) )拿分的,但这显然不是我们的目标。
有关于LCS的代码实现,本篇博客不再过多说明,我们主要来说一下如何在这道题拿1000%的分数。
首先我们需要注意一个点:
关键1:关于这两个序列,它们是不同顺序的同数据序列。
这个点很重要,它将是我们解决这道题的关键。
接下来,引入第二个关键点:
我们假设序列1是严格递增的,这里所说的严格递增并不是实际意义上的递增。
比如序列1为1 2 5 3 4,我们认为5就是比3小,4就是这五个数最大的。
此时序列1为严格递增的。
那么对于序列1来说,序列2是我的一个排列组合,如果序列2要和我重合,那么重合部分的大小规则必须和我一致。
也就是说,
关键2:序列2和序列1的LCS长度,就是在序列2严格遵守序列1的排序规则下所能产生的LIS的长度。
如果你领悟了以上两点,那么这道题就非常简单了。
建议不懂的再仔细想想,结合样例去理解。
先想一下这个样例:
123456
321546
再带入博客中所说的两个关键点,想一下这个样例:
315264
135264
接下来就只是枯燥的代码环节了。
由小卷子为大家奉上代码。
Part4:AC代码
#include<iostream>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
int a[maxn],b[maxn];
int dp[maxn],num[maxn];
int main()
{
ios::sync_with_stdio(false);
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],num[a[i]]=i;
///寻找自己在对方的位置,相当于遵守对方的排序规则
for(int i=1;i<=n;i++) cin>>b[i],b[i]=num[b[i]];
dp[1]=b[1];
int len=1;
///nlogn的LIS
for(int i=2;i<=n;i++)
{
if(b[i]>dp[len]) dp[++len]=b[i];
else
{
int pos=lower_bound(dp+1,dp+1+len,b[i])-dp;
dp[pos]=b[i];
}
}
//for(int i=1;i<=len;i++) cout<<dp[i]<<" ";
cout<<len<<endl;
}
/*7 6 3 9 8 5 4 1 2
1 2 3 4 5 6 7 8 9
8 9 3 7 6 2 1 5 4*/
一开始自己也是没想懂,后来看到了一些东西,被启发了。
也感谢漂亮学姐的提问,使得我思路更加清楚了,于是满腔热血的写了下来。
Part5:死宅时间
取自《银魂》13集
坂田银时:
“人的一生,就仿佛身负沉重行李走在遥远的旅程上。”
这句话,是以前一个叫德川田信秀的大叔说的。
初听觉得是句很烦人的话,可是慢慢想想,老人家的话果然还是有道理啊。
也许算不上什么行李,不过任何人的双臂中都抱着些珍贵的东西。
但拥有的时候永远不会留意到,注意到那份沉重却是在一切都从手中悄然滑落了的时候。
不知道多少次的反复想着,那种玩意儿再也不要拥有了。
可是,不知道什么时候又背起了。 也许索性全部抛弃会比较轻松,可无论如何还是不想那样做。
因为没有那些家伙的话,旅程将多么无趣啊。