http://acm.hdu.edu.cn/showproblem.php?pid=1025
题意:富人路与穷人路都分别有从1到n的n个点,现在要在富人点与穷人点之间修路,但是要求路不能交叉,问最多能修多少条。
思路:穷人路是按顺序给的,故求富人路的最长上升子序列即可。由于数据范围太大,应该用O(nlogn)的算法求LIS。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 using namespace std; 5 const int N=500005; 6 int r[N],d[N]; 7 int main() 8 { 9 int n,cnt = 0,x,y,k; 10 while(~scanf("%d",&n)) 11 { 12 cnt++; 13 memset(d,0,sizeof(d)); 14 for (int i = 0; i < n; i++) 15 { 16 scanf("%d %d",&x,&y); 17 r[x] = y; 18 } 19 k = 1; 20 d[k] = r[1]; 21 for (int i = 2; i <= n; i++) 22 { 23 int low = 1; 24 int high = k; 25 int mid; 26 while(low <= high) 27 { 28 mid = (low+high)/2; 29 if (d[mid] < r[i]) 30 low = mid+1; 31 else 32 high = mid-1; 33 } 34 d[low] = r[i]; 35 if (low > k) 36 k = low; 37 } 38 if (k==1) 39 printf("Case %d: My king, at most %d road can be built. ",cnt,k); 40 else 41 printf("Case %d: My king, at most %d roads can be built. ",cnt,k); 42 } 43 return 0; 44 }