http://acm.pku.edu.cn/JudgeOnline/problem?id=2533
最長上升子序列:
有兩種基本方法:兩個時間復雜度分別為O(n^2)和O(nlogn)
先來看第1種:
動態規劃:
對于給定數列E,元素個數為n,最長上升子序列Q滿足對任意1<=i<j<=n,有Q[i]<Q[j],且E[i]<E[j]。
容易得出O(n^2)的DP遞推公式:
D[i]=max{D[j]}+1;(1<=j<i且E[j]<E[i])
D[i]為以元素i結尾的最長子序列個數。
這樣經過兩重循環一次遍歷可以得到最長上升子序列。
代碼如下:
#include<iostream>
using namespace std;
int n;
int a[1001],b[1001];
int main()


{ int i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)

{
scanf("%d",&a[i]);
b[i]=1;
}
for(i=1;i<=n;i++)

{ int maxx=0;
for(j=1;j<=i;j++)

{
if(a[i]>a[j]&&b[j]>maxx)

{ maxx=b[j];
}
}
b[i]=maxx+1;
}
int best=0;
for(i=1;i<=n;i++)

{ if(best<b[i])
best=b[i];
}
printf("%d\n",best);
system("pause");
return 0;
}


第2種方法時間復雜度為O(nlogn),用到了二分查找和貪心。
其操作如下:
開辟一個棧,每次取棧頂元素s和讀到的元素a做比較,如果a>s,則加入棧;如果a<s,則二分查找棧中的比a大的第1個數,并替換。最后序列長度為棧的長度。
這也是很好理解的,對x和y,如果x<y且E[y]<E[x],用E[x]替換E[y],此時的最長序列長度沒有改變但序列Q的''潛力''增大。
舉例:原序列為1,5,8,3,6,7
棧為1,5,8,此時讀到3,則用3替換5,得到棧中元素為1,3,8,再讀6,用6替換8,得到1,3,6,再讀7,得到最終棧為1,3,6,7,最長遞增子序列為長度4。
代碼如下:
#include<iostream>
using namespace std;
int n;
int a[1001],b[1001];
int rear;
int solve(int t)


{ int l=1,r=rear;
while(l<=r)

{ int mid=(l+r)>>1;
if(b[mid]>=t)//若為非遞減序列,則為b[mid]>t
r=mid-1;
else
l=mid+1;
}
if(l>rear)
rear=l;
return l;
}
int main()


{ int i,j;
scanf("%d",&n);
rear=0;
for(i=1;i<=n;i++)

{
scanf("%d",&a[i]);
b[solve(a[i])]=a[i];
}
printf("%d\n",rear);
system("pause");
return 0;
}

