POJ2533裸的LIS,时间复杂度为O(n^2)
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int MAXN=1000+5; 5 int a[MAXN]; 6 int dp[MAXN]; 7 int n,ans; 8 9 int main() 10 { 11 scanf("%d",&n); 12 for (int i=0;i<n;i++) 13 { 14 scanf("%d",&a[i]); 15 dp[i]=1; 16 } 17 ans=-1; 18 for (int i=1;i<n;i++) 19 { 20 for (int j=0;j<i;j++) 21 if (a[j]<a[i] && dp[j]+1>dp[i]) 22 { 23 dp[i]=dp[j]+1; 24 } 25 if (dp[i]>ans) 26 { 27 ans=dp[i]; 28 } 29 } 30 cout<<ans<<endl; 31 return 0; 32 }
POJ1631
两条线路i与j不交叉的前提条件是a[i]<a[j],即上升子序列。用二分搜索+LIS,时间复杂度为O(n^2),具体解释详见《挑战程序设计竞赛2.3记录结果在利用的“动态规划”》P65
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int MAXN=40000+5; 5 const int INF=1000000+5; 6 int a[MAXN]; 7 int dp[MAXN];//dp[i]表示长度为i+1的上升子序列末位元素的最小值 8 int n,m,ans,l,r; 9 10 int search(int k) 11 { 12 int ul=l,ur=r; 13 while (ur-ul>1) 14 { 15 int mid=(ur+ul)/2; 16 if (dp[mid]>=k) ur=mid; 17 else ul=mid; 18 } 19 return ur; 20 } 21 22 int main() 23 { 24 scanf("%d",&m); 25 for (int kase=0;kase<m;kase++) 26 { 27 scanf("%d",&n); 28 for (int i=0;i<n;i++) 29 { 30 scanf("%d",&a[i]); 31 dp[i]=INF; 32 } 33 l=-1; 34 r=0; 35 for (int i=0;i<n;i++) 36 { 37 int pos=search(a[i]); 38 dp[pos]=a[i]; 39 if (pos==r) r++; 40 } 41 cout<<r<<endl; 42 } 43 return 0; 44 }
时间: 2024-10-21 00:35:40