题目叙述
现在他们位于神秘森林的核心部位,面前有两条主要的大道,不用说,一条通向光明,一条通向黑暗。大家当然想奔向光明,远离黑暗,可是蓬絮研究了半个时辰也研究不出个所以然。
倒是细心的花楹发现了线索,她在地上搜寻时,发现了遗落在草丛里的一张纸,纸上如是写道:
致想要寻找出口的人们:
这里必须你们真正了解大地的运行规律,才能破解难关。
现在,你们只需要拿这这张纸,大喊一声:“哇呱呱呱呱呱呱呱呱呱呱~”,你们前方的地面上就会出现很多的木偶士兵,他们外貌各异。你们必须把他们排布成东边一棵松树上刻纹中写出的阵列,正确的出口才会显露出来。
正确的答案就在你们面前,只看你们能不能把握咯。
——米不亚亚亚亚尔之主:巴罗罗罗罗列吉
没办法,虽然这张破破烂烂发着臭气的纸看上去不像真的,死马当作活马医,三人还是照做了。没想到咒语刚说完,前方“嗡~”的一声起了巨大的烟雾。等到烟消云散,三兽定睛一看,地上果然出现了数不清的人偶。
他们开始相信这一张纸的真实性了,动作快的勇气赶忙找到附近的一棵松树。果然,上面也刻着数不请的人偶图案。
现在的任务就是如何调整木偶的顺序了。整个木偶群可以看成一列排布的,所有的 n 个木偶不尽相同,编号为 1-n。由于仙兽功力有限,每次施法只能把一个木偶移动到另两个木偶之间(可以移到队头和队尾)。
经过三个时辰的仔细研究,勇气已经把所有的木偶都正确编号完毕(勇气:累死俺也~她们两个都不干事的……)。现在他需要你告诉他,要完成调整最少需要移动多少次木偶,这样来给他个心里准备……
数据范围
对于 60% 的数据,n <= 1000
对于 100% 的数据,n <= 100000
input:
三行,第一行一个整数 n,表示有 n 个木偶。
第二行,n 个整数(1-n),表示初始时木偶的排布。
第三行,n 个整数(1-n),表示目标木偶的排布
output:
一行,一个整数,表示最少移动次数。
样例解释
先把 1 移动到 10 后面,后面 2-9 每个数移动到 10 和 1 中合适的位置,则 10 不需要移动,共移动 9 次
input:
10
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
output:
9
分析:
此题有两个方法:
1:求两个序列的最长公共子序列。两个的最长公共子序列,一看似乎没有什么关系,而更多的是想到排序什么的(本人菜一开始也是如此),但是仔细一想有些窍门。
原理:两个序列,他们都是1--N的元素组成的,而且对于每个序列都包含了对方的那个序列的元素,那么我们可以假设对于两个序列是否存在一些公共(即一样顺序)顺序的元素是我们不需去调换的,想到这,算法不禁的已经出现在眼前:就是求去两个序列的最长公共子序列,最后用总数减去那些不需调换(即最长公共子序列的个数)的个数,就是答案了。
注意:数据是60%的1000,100%的100000,所以你只能那60分,小数据用此方法,100000用下面的。
2:求最长的不降子序列。最长的不降子序列,几乎没有表面现象什么可以看出是此算法。
原理:仔细想一下,如果我们把第一个序列按1 2 3 4 5.......N这样顺序的编号,然后再把第二序列的数值在第一个标号的序列里所对应的标号对应的写入序列中,不要改变位置。
例如: 序列1: 1 2 3 4 5 序列2:5 3 1 2 4
下标: 1 2 3 4 5 对应序列1的下标:5 3 1 2 4
那么,现在再看一次序列2的下标,它的值所对应的序列1的下标就组成了一个以序列1的先后出现顺序的一个序列,那么我们把这些出现的先后找到一个最长的上升子序列,不就是序列1中所不用调换的最大个数吗?其它的则是需要调换的啦.这样此题就完美解决啦。
【参考程序】:
#include<iostream>
using namespace std;
int a[100001],b[100001];
int c[100001];
int n,size;
int bsearch(int ai)
{
int l=1,r=size,mid;
while (l<=r)
{
mid=(l+r)>>1;
if (c[mid-1]<=ai && ai<c[mid]) return mid;
else if (ai>c[mid]) l=mid+1;
else r=mid-1;
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
c[b[i]]=i;
}
int k;
for (int i=1;i<=n;i++)
{
scanf("%d",&k);
a[i]=c[k];
}
c[1]=a[1];size=1;
for (int i=2;i<=n;i++)
{
int j;
if (a[i]<=c[1]) j=1;
else if (a[i]>c[size]) j=++size;
else j=bsearch(a[i]);
c[j]=a[i];
}
printf("%d\n",n-size);
return 0;
}