HDU1025-二分求LIS。
阿新 • • 發佈:2019-01-02
1.題目連結。說了很多,但是一句話可以概括。在平行線的之間有一些線段,取一組線段使得任意兩條不相交,求最多有多少條這樣的線段。
2.分析:為什麼就是轉化成了LIS了呢?其實這個很簡單,我們只需要考慮一條邊,從1到n,然後把另一條邊上的數字對映上來,並且是一一對應的,所以就是個陣列了。a[i]=j;代表i和j之間有一條線段,做完這個對映之後,我們可以觀察到,如果在poor cities中,i<j的,那麼如果二者不相交,就a[i]就必然是小於a[j]的。就是一種偏序關係。知道了這個,求最多滿足的那麼就是求LIS了,但是如果只是普通的n2的做法,必然是不行的,這裡我們採用二分將複雜度下降為nlogn即可。下面是程式碼:
#include<iostream> #include<algorithm> #pragma warning(disable:4996) int dp[50005], a[50005];//dp[i]表示已a[i]為結尾的最長的上身子序列的最後一個數據 //找長度為n的最長的上升子序列 int Lis(int n) { int len = 1, i, low, high, mid; dp[1] = a[1]; for (i = 2; i <= n; i++) { low = 1; high = len; while (low <= high) { mid = (low + high) / 2; if (a[i]>dp[mid]) low = mid + 1; else high = mid - 1; } dp[low] = a[i]; if (low>len) len = low; } return len; } int main() { int n, x, y, i, ans, k = 1; while (scanf("%d", &n) != EOF) { for (i = 0; i<n; i++) { scanf("%d%d", &x, &y); a[x] = y; } ans = Lis(n); printf("Case %d:\n", k++); if (ans == 1) printf("My king, at most 1 road can be built.\n"); else printf("My king, at most %d roads can be built.\n", ans); printf("\n"); } return 0; }