日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一中OJ #1438 航线设计 | LIS 序列DP | 解题报告

發布時間:2024/1/1 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一中OJ #1438 航线设计 | LIS 序列DP | 解题报告 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一中OJ | #1438 航線設計

時限 1000MS/Case 內存 64MB/Case





題目描述

有一個國家被一條河劃分為南北兩部分,在南岸和北岸總共有N對城鎮,每一城鎮在對岸都有唯一的友好城鎮。任何兩個城鎮都沒有相同的友好城鎮。每一對友好城鎮都希望有一條航線來往。于是他們向政府提出了申請。由于河終年有霧。政府決定不允許有任兩條航線交叉(如果兩條航線交叉,將有很大機會撞船)。
你的任務是寫一個程序來幫政府官員決定他們應撥款興建哪些航線以使得沒有出現交叉的航線最多。?

輸入格式

第一行一個整數N,表示分布在河兩岸的城鎮對數。接下來的N行每行有兩個由空格分隔的正數C,D(C、D<=10^9〉,描述每一對友好城鎮沿著河岸與西邊境線的距離,C表示北岸城鎮的距離而D表示南岸城鎮的距離。在河的同一邊,任何兩個城鎮的位置都是不同的。

輸出格式

在安全條件下能夠開通的最大航線數目。

樣例輸入

7
22 4
2 6
10 3
15 12
9 8
17 17
4 2

樣例輸出

4

數據范圍

1<=N<=500000

----------------------------------------------------------

題目分析

將上下兩端看成匹配,假設有航線A<-->B和航線C<-->D,它們不交叉的條件是AB的不等關系與CD相同(當A<B時C<D 或 當A>B時C>D)

那么將每條航線按北端點進行排序,在搜索A的時候,A一定是小于A后面的所有元素的,那么這個時候只需要找一個大于C的D即可。

因為北端點已經有序了,那么只需要對南端點的序列找LIS就可以保證一定不會相交啦

----------------------------------------------------------

關于NlogN找LIS的方法

網上已經有無數篇介紹這個方法的啦,但是還是說一下吧

設數組d儲存當前的最小字典序的LIS序列

也就是d[i]代表當前長度為i的LIS的第i位的最小值

動態維護d數組,假設當前最長長度為ans,那么當a[i+1]大于d[ans]的時候把d[ans+1]改成a[i],表示找到了長度為ans+1的LIS,ans+1

當a[i+1]不大于d[ans]的時候二分找a[i+1]能排到什么位置,然后與d[x]替換,即可保證d數組一定是字典序最小的LIS序列


更詳細的解釋來自我寫代碼的時候敲的注釋::

/*
設d[i]為長度為i的LIS的末尾元素的最小值
對d[i]進行維護使得d[i]保持單調遞增性
設當前DP找到的LIS長度為i,當找長度為i+1的LIS的時候就可以使用二分查找來找比d[i]大的最小值
那么如何對一個沒有排序的序列進行二分查找呢?這顯然是不現實的
其實只需要對d進行二分查找,找到的i就是以當前a[x]為末尾的LIS長度
此時為了保證d[i]是長度為i的LIS的末尾元素的最小值,對d[i]進行更新,d[i]=min(d[i],當前數字)
如果二分查找的結果是d數組的末尾+1,說明當前數字可以插入LIS中,再把d[i]更新成當前數字即可

------

特別注意,{d[i] | i>0}的初始值應該為inf,這樣可以保證無論如何都可以替換d[i]
*/

----------------------------------------------------------

代碼

#include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <set> #include <queue> #include <stack> #include <vector> #include <map> #define hashsize 1000003 #define inf 0x7f7f7f7f using namespace std; struct node {friend bool operator <(node a,node b){return a.north<b.north;}int north;int south; }line[500005]; int d[500005],a[500005],ans=0,n; int main() {scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d%d",&line[i].north,&line[i].south);sort(line+1,line+1+n);for(int i=1;i<=n;i++) a[i]=line[i].south;for(int i=1;i<=n;i++) d[i]=inf;d[0]=-inf;for(int i=1;i<=n;i++){int p=upper_bound(d+1,d+ans+1,a[i])-d;//當p為ans+1時,說明當前數字可以插入LISif(p==ans+1){ans++;d[ans]=a[i];}else d[p]=min(d[p],a[i]);}cout<<ans;return 0; }

總結

以上是生活随笔為你收集整理的一中OJ #1438 航线设计 | LIS 序列DP | 解题报告的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。