题目链接:http://poj.org/problem?id=1631
先确定一方有序后,就是LIS问题了。
仔细观察上图:红色航线是合法的,那么他们满足什么规律呢?
C1 C2 C3 C4
北岸红线的端点: 4 9 15 17
南岸红线的端点: 2 8 12 17
D1 D2 D3 D4
不难看出无论线的斜率如何,都有这样的规律:
C1<C2<C3<C4 且 D1<D2<D3<D4
如果我们把输入数据排升序,问题变抽象为:
在一个序列(D)里找到最长的序列满足DI<DJ<Dk……且i<j<k
这样的话便是典型的最长非降子序列问题了。。。。
法二:边界条件法(我前面总结提到的第4个方法)
边界法其实就是把数据往小了缩,显然N=1是答案是1。N=2时呢?
考虑这样一组数据:
N=2
C1 D1
C2 D2
当 C1<C2 时,如果D1>D2 那么一定会相交,反之则不会相交。
当C1 >C2时,如果D1<D2 那么一定会相交,反之则不会相交。
N=3
C1 D1
C2 D2
C3 D3
……
其实不用在推导N=3了,有兴趣的可以推导去。看N=2时就能得出:
对于任意两条航线如果满足Ci<Cj 且Di<Dj 则两条航线不相交。这样的话要想在一个序列里让所有的航线都不相交那比然满足,C1<C2<C3…Cans且D1<D2<D3…<Dans ,也就是将C排序后求出最长的满足这个条件的序列的长度就是解。
这样分析后显然是一个最长非降子序列问题。<摘自动态规划经典教程> ( 很不错的一本书,强烈推荐!)
1 //STATUS:C++_AC_125MS_448KB 2 #include <functional> 3 #include <algorithm> 4 #include <iostream> 5 //#include <ext/rope> 6 #include <fstream> 7 #include <sstream> 8 #include <iomanip> 9 #include <numeric> 10 #include <cstring> 11 #include <cassert> 12 #include <cstdio> 13 #include <string> 14 #include <vector> 15 #include <bitset> 16 #include <queue> 17 #include <stack> 18 #include <cmath> 19 #include <ctime> 20 #include <list> 21 #include <set> 22 #include <map> 23 using namespace std; 24 //define 25 #define pii pair<int,int> 26 #define mem(a,b) memset(a,b,sizeof(a)) 27 #define lson l,mid,rt<<1 28 #define rson mid+1,r,rt<<1|1 29 #define PI acos(-1.0) 30 //typedef 31 typedef __int64 LL; 32 typedef unsigned __int64 ULL; 33 //const 34 const int N=40010; 35 const int INF=0x3f3f3f3f; 36 const int MOD=100000,STA=8000010; 37 const LL LNF=1LL<<60; 38 const double EPS=1e-8; 39 const double OO=1e15; 40 const int dx[4]={-1,0,1,0}; 41 const int dy[4]={0,1,0,-1}; 42 //Daily Use ... 43 inline int sign(double x){return (x>EPS)-(x<-EPS);} 44 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} 45 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} 46 template<class T> inline T Min(T a,T b){return a<b?a:b;} 47 template<class T> inline T Max(T a,T b){return a>b?a:b;} 48 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);} 49 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);} 50 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));} 51 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));} 52 //End 53 54 int num[N],f[N]; 55 int T,n; 56 57 int binary(int l,int r,int tar) 58 { 59 int mid; 60 while(l<r){ 61 mid=(l+r)>>1; 62 if(f[mid]<=tar)l=mid+1; 63 else r=mid; 64 } 65 return l; 66 } 67 68 int main() 69 { 70 // freopen("in.txt","r",stdin); 71 int i,j,l,r,k; 72 scanf("%d",&T); 73 while(T--) 74 { 75 scanf("%d",&n); 76 for(i=0;i<n;i++){ 77 scanf("%d",&num[i]); 78 } 79 80 l=1;r=2; 81 f[1]=INF; 82 for(i=0;i<n;i++){ 83 k=binary(l,r,num[i]); 84 f[k]=num[i]; 85 r=Max(r,k+1); 86 } 87 88 printf("%d\n",r-1); 89 } 90 return 0; 91 }