试题描述 |
吉丽王国有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,显然是最大值。 【数据规模】 |
【分析】
一开始的想法是先预处理然后求个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 }
时间: 2024-11-08 21:06:59