P1020 导弹拦截(n*log n时间的最长上升子序列思想)
題目描述
某國為了防御敵國的導彈襲擊,發展出一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以后每一發炮彈都不能高于前一發的高度。某天,雷達捕捉到敵國的導彈來襲。由于該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的導彈。
輸入導彈依次飛來的高度(雷達給出的高度數據是\le 50000≤50000的正整數),計算這套系統最多能攔截多少導彈,如果要攔截所有導彈最少要配備多少套這種導彈攔截系統。
輸入格式
11行,若干個整數(個數\le 100000≤100000)
輸出格式
22行,每行一個整數,第一個數字表示這套系統最多能攔截多少導彈,第二個數字表示如果要攔截所有導彈最少要配備多少套這種導彈攔截系統。
輸入輸出樣例
輸入 #1復制
389 207 155 300 299 170 158 65
輸出 #1復制
6
2
思路:dp[i]是代表i長度的上升子序列的最后一個數(也是最小的數)
i的最大值即為最長上升子序列。
對于a[i] 和a[j],a[i]>a[j] 以他們為結尾的上升子序列長度相等,
因此我們可以用a[j]來代替a[i],如果在后續中,k>a[i],就一定有k>a[j],但是k>a[j],就不一定有k>a[i],所以a[i]可以說是已經沒用了,可以完全由a[j]代替。
具體模板代碼:
#include<bits/stdc++.h> #define INF 0x3f3f3f3f3f3f3f3f #define inf 0x3f3f3f3f #define FILL(a,b) (memset(a,b,sizeof(a))) #define re register #define lson rt<<1 #define rson rt<<1|1 #define lowbit(a) ((a)&-(a)) #define ios std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0); #define fi first #define rep(i,n) for(int i=0;(i)<(n);i++) #define rep1(i,n) for(int i=1;(i)<=(n);i++) #define se secondusing namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int > pii; int dx[4]= {-1,1,0,0},dy[4]= {0,0,1,-1}; const ll mod=10007; const ll N =1e6+10; const double eps = 1e-4; const double pi=acos(-1); ll gcd(int a,int b){return !b?a:gcd(b,a%b);} int dp1[N]; int dp2[N]; int a[N],n; int main() {ioswhile (cin >> a[++n]); n--;int len1=1,len2=1;dp1[1]=a[1];dp2[1]=a[1];for(int i=2;i<=n;i++){if(dp1[len1]>=a[i]) dp1[++len1]=a[i];else {int pos=upper_bound(dp1+1,dp1+1+len1,a[i],greater<int>())-dp1;dp1[pos]=a[i];}if(dp2[len2]<a[i]) dp2[++len2]=a[i];else {int pos=lower_bound(dp2+1,dp2+1+len2,a[i])-dp2;dp2[pos]=a[i];}}cout<<len1<<endl<<len2; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的P1020 导弹拦截(n*log n时间的最长上升子序列思想)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Alienware 推出世界最大机械键盘
- 下一篇: P1833 樱花——混合背包 二进制优化