首页 > 代码库 > Laoj P1659 noip模拟 - 道路规划(LCS的nlogn算法)
Laoj P1659 noip模拟 - 道路规划(LCS的nlogn算法)
试题描述
|
吉丽王国有n个城市,每个城市有两个“附属城市”,其中北部有n个城市,每个城市的编号都是1~n中的一个,且互不相同,南部的n个城市也是如此。
很遗憾,南北两边的城市之间还没有道路连接,这个南北交通运输带来了很大的麻烦。 国王吉丽设计规划了一种方案,决定先建n条道路,即编号相同的两个城市之间连上一条道路。 如图所示,这就是建完道路后的样子。 如果第i个城市和第j个城市的两条道路相交了,那么我们称这两个城市“平等互惠”。 吉丽想找出一个城市集合,使得集合中的任意两个城市都“平等互惠”,吉丽还希望这个集合的大小尽可能大。 那最大是多少呢,请你回答他。 |
输入格式
|
第一行,一个整数,n。
第二行,n个整数,第i个数表示北部第i个城市的编号。 第三行,n个整数,第i个数表示南部第i个城市的编号。 |
输出格式
|
输出合法的城市集合的最大大小。
|
输入示例
|
5
1 4 5 2 3 3 4 2 1 5 |
输出示例
|
3
|
注释说明
|
【样例解释】
{1,3,4},{1,2,3}和{2,3,5}都是合法的方案,大小是3,显然是最大值。 【数据规模】 对于20%数据,n<=50; 对于50%数据,n<=500; 对于70%数据,n<=5000; 对于100%数据,n<=10^5。 |
【分析】
一开始的想法是先预处理然后求个lis之类的,也算靠了点边。
后来发现把第二个序列翻转后,取二者的lcs即可,数据范围10^5,明显留给nlogn的。
LCS的nlogn算法其实就是把LCS转成LIS,LIS的nlogn算法想必大家都会了。
怎么转化呢,举个栗子:
比如样例数据是1 4 5 2 3和3 4 2 1 5,第二个序列翻转后为5 1 2 4 3,用c[i]来表示第一个序列的第i个数在第二个序列中的位置。
此时c[5]={4, 2, 5, 3, 1},现在再对c数组求LIS就可以了。
注意,要求是集合中任意两个城市都为“平等互惠”,如果我们求出来LCS=1的话,这个集合就为空。
【代码】
1 #include <bits/stdc++.h> 2 #define inf 0x7fffffff 3 using namespace std; 4 5 int n, a[100005], b[100005], c[100005], x, g[100005], ans, k, f[100005]; 6 7 void init() { 8 cin >> n; 9 for (int i=1;i<=n;++i) 10 scanf("%d", &a[i]); 11 for (int i=n;i>0;--i) { 12 scanf("%d", &x); 13 b[x]=i; 14 } 15 for (int i=1;i<=n;++i) 16 c[i]=b[a[i]]; 17 } 18 19 void lis() { 20 for (int i=1;i<=n;++i) 21 g[i]=inf; 22 for (int i=1;i<=n;++i) { 23 k=lower_bound(g+1, g+n+1, c[i])-g; 24 g[k]=c[i]; 25 f[i]=k; 26 ans=max(ans, f[i]); 27 } 28 } 29 30 int main() { 31 init(); 32 lis(); 33 if (ans!=1) 34 cout << ans << endl; 35 else 36 cout << 0 << endl; 37 }
Laoj P1659 noip模拟 - 道路规划(LCS的nlogn算法)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。