1. 程式人生 > >Laoj P1659 noip模擬 - 道路規劃(LCS的nlogn算法)

Laoj P1659 noip模擬 - 道路規劃(LCS的nlogn算法)

ble jpg hspa 都是 target net borde 輸入 c數組

試題描述
吉麗王國有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算法)