這種問題一般都比較熟悉,我們先看n^2的算法
導彈攔截
時間限制: 1 Sec 內存限制: 128 MB提交: 106 解決: 61
[提交][狀態][討論版]
題目描述
某國為了防御敵國的導彈襲擊,發展出一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意 的高度,但是以后每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的導彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所 有的導彈。
輸入導彈一次飛來的高度(雷達給出的高度不大於30000的正整數)。計算這套系統最多能攔截多少導彈。
輸入
n顆依次飛來的導彈高度,導彈顆數<=1000。
輸出
一套系統最多攔截的導彈數。
樣例輸入
7 300 250 275 252 200 138 245
樣例輸出
5
令f[i]表示前i個數的最長序列長度f[j]=max(f[j],f[i]+1)i<j且a[i]>=a[j]
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int n,a[1005],f[1005],ans; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) { f[i]=1; for(int j=1;j<i;j++) if(a[j]>=a[i])f[i]=max(f[i],f[j]+1); } for(int i=1;i<=n;i++) ans=max(ans,f[i]); cout<<ans<<endl; }
但是在一些n=100000的題目上O(n^2)的算法會時間超限。我們考慮優化這一算法。令B[i]=長度位i的序列最后一個一個字符的最大值。
對於新進來的一個數,我們看其能否跟新B數組中的一個值。如何跟新一個值呢?二分查找。
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int n,B[100005],a[100005],len; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); B[1]=-a[1],len=1; for(int i=2;i<=n;i++) { if(-a[i]>=B[len]) B[++len]=-a[i]; else { int pos=upper_bound(B+1,B+len,-a[i])-B; B[pos]=-a[i]; } } cout<<len<<endl; }
就是很短的代碼實現了nlogn的類lis功能。