欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > P1439 【模板】最长公共子序列

P1439 【模板】最长公共子序列

2025/4/19 7:19:23 来源:https://blog.csdn.net/hemingyuan123/article/details/147152154  浏览:    关键词:P1439 【模板】最长公共子序列

题目描述

给出 1 , 2 , … , n 1,2,\ldots,n 1,2,,n 的两个排列 P 1 P_1 P1 P 2 P_2 P2 ,求它们的最长公共子序列。

输入格式

第一行是一个数 n n n

接下来两行,每行为 n n n 个数,为自然数 1 , 2 , … , n 1,2,\ldots,n 1,2,,n 的一个排列。

输出格式

一个数,即最长公共子序列的长度。

输入输出样例 #1

输入 #1

5 
3 2 1 4 5
1 2 3 4 5

输出 #1

3

说明/提示

  • 对于 50 % 50\% 50% 的数据, n ≤ 1 0 3 n \le 10^3 n103
  • 对于 100 % 100\% 100% 的数据, n ≤ 1 0 5 n \le 10^5 n105

题目分析

类似题目:友好城市。

把题目转化一下:
每一个数只会在两个串之间出现一次,我们要将这两个数字连起来,这样就会产生一条线段,每两条线段之间不能有交叉,求解最多可添加的线段条数

如何添加更多线段?

假设现在有两个线段,端点分别为 x 1 , y 1 x_1,y_1 x1,y1 x 2 , y 2 x_2,y_2 x2,y2 能添加的条件就是 $x_1 < x_2 $ 且 y 1 < y 2 y_1 < y_2 y1<y2

这样只需要让两个端点的值尽量小并且都保持从小到大的顺序
这不就是最长上升子序列吗!

可以以任意一个位置为关键字由小到大排序,再求另一个关键字所组成的最长不下降子序列长度,输出即可

定义: d p [ i ] dp[i] dp[i] 长度为 i i i 的最长上升子序列的最小结尾

算法: 二分减少时间复杂度

for(int i = 1 ; i <= n ; i++){if(cty[i].second > dp[cnt])dp[++cnt] = cty[i].second;//比最大的还大,直接加一个新的else *lower_bound(dp+1,dp+cnt+1,cty[i].second) = cty[i].second;//找到第一个比他大的替换
}

AC代码

#include<bits/stdc++.h>using namespace std;const int SIZN = 1e5 + 10;int n;
pair<int,int> cty[SIZN];
int dp[SIZN],cnt = 0;
bool cmp(pair<int,int> a,pair<int,int> b){return a.first < b.first;
}
signed main(){cin >> n;for(int i = 1 ; i <= n ; i++){int k;cin >> k;cty[k].first = i;}for(int i = 1 ; i <= n ; i++){int k;cin >> k;cty[k].second = i;}sort(cty+1,cty+n+1,cmp);for(int i = 1 ; i <= n ; i++){if(cty[i].second > dp[cnt])dp[++cnt] = cty[i].second;else *lower_bound(dp+1,dp+cnt+1,cty[i].second) = cty[i].second;}cout << cnt;return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词