Leyni的情人节 | ||||||
| ||||||
Description | ||||||
Leyni在情人节组织了一场游戏,聚集了n对情侣,编号为1..n,男生一行,女生一行,两排平行,打乱顺序后,每对情侣用一条线迁在一起,如下图:
| ||||||
Input | ||||||
输入包含多组测试数据。 对于每组测试数据: 第1行,包含一个整数n (1 ≤ n ≤ 105) 第2行,包含n个不同的1到n的整数,代表男生的位置顺序。 第3行,包含n个不同的1到n的整数,代表女生的位置顺序。 处理到文件结束 | ||||||
Output | ||||||
对于每组测试数据: 第1行,输出这组线含多少条。 | ||||||
Sample Input | ||||||
5 1 5 3 4 2 2 3 1 5 4 | ||||||
Sample Output | ||||||
3 | ||||||
Hint | ||||||
1 2 3满足两两相交 | ||||||
Author | ||||||
齐达拉图@HRBUST |
思路(这是一个比较隐秘的模型O.O):
1、因为要一一对应才能连线,那么我们不如搞出一个数组c【i】表示第一行第i个位子上的数字在第二行的什么位子上。
2、又因为要求两两相连,那么其实我们枚举出来两种情况不难推敲出如何继续做:
①
1 3 2
1 2 3
此时c【】:
1 3 2
ans=2;最长递减子序列:3 2
②
1 3 2
2 3 1
此时c【】:
3 2 1
ans=3;最长递减子序列:3 2 1
其实结果就是在求C【】的最长递减子序列长度。
因为要求交叉才能相连,所以肯定是第一行前边的数字在第二行的越后边,其可能得到的结果就越长,根据这个思路,也不难想到要求c 【】的最长递减子序列长度。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int a[100060];
int b[100060];
int pos[100060];
int c[100060];
int res[100060];
int n;
int find(int n,int key)
{
int left=0;
int right=n;
while(left<=right)
{
int mid=(left+right)/2;
if(res[mid]>key)
{
left=mid+1;
}
else
{
right=mid-1;
}
}
return left;
}
int Lis(int a[],int n)
{
int r=0;
res[r]=a[0];
r++;
for(int i=1;i<n;i++)
{
if(res[r-1]>a[i])
{
res[r]=a[i];
r++;
}
else
{
int loc=find(r,a[i]);
res[loc]=a[i];
}
}
return r;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)scanf("%d",&a[i]);
for(int i=1; i<=n; i++)
{
scanf("%d",&b[i]);
pos[b[i]]=i;
}
for(int i=1; i<=n; i++)
{
c[i]=pos[a[i]];
}
for(int i=0; i<n; i++)
{
a[i]=c[i+1];
}
int output=Lis(a,n);
printf("%d\n",output);
}
}