P1020 [NOIP1999 普及组] 导弹拦截

题目链接:https://www.luogu.com.cn/problem/P1020
思路:题目要求输出两个数,分别是用一个系统最多可以拦截多少个,用几个系统可以全部拦截。
由于系统每发炮弹发射的高度不能高于上次发射炮弹的高度,所以我们找到从某个炮弹开始,他后面的炮弹的高度不高于他的个数。找到这个数的最大值就是用一个系统可以拦截的最大个数。那么也就是求到某个数的最长不上升子序列。
第二问求用几个系统可以全部拦截,由于系统没发炮弹发射的高度不能高于上次炮弹发射的高度,所以,如果当前炮弹的高度比上一个炮弹的高度高那么就不能拦截,假设当前大炮为i,那么i的范围就是1-n,n是导弹的个数。
所以我们要求出到第i个数的最长上升子序列
求最长不上升子序列 设dp[i]为到第i个数的最长不上升子序列,如果arr[j]>=arr[i] 那么dp[i]=dp[j]+1; j的范围是1-i-1
求最长上升子序列 设dp[i]为到第i个数的最长上升子序列,如果arr[j]<arr[i],那么dp[i]=dp[j]+1; j的范围是1-i-1

下面这个代码提交只能过的100分,因为这是用O(N²)的方法求的
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int arr[maxn],n;
int dp1[maxn],dp2[maxn];
void INPUT(){
    while(cin>>arr[++n]);
    n--;
}

void solve(){
    int a=0;
    for(int i=1;i<=n;i++){
        dp1[i]=1;
        //cout<<"i:"<<i<<" "<<arr[i]<<endl;
        for(int j=i-1;j>=1;j--){
            if(arr[j]>=arr[i]){
                //cout<<j<<" "<<arr[j]<<endl;
                dp1[i]=max(dp1[i],dp1[j]+1);
            }
        }
        a=max(a,dp1[i]);
    }
    cout<<a<<endl;
    
    int b=0;
    for(int i=1;i<=n;i++){
        dp2[i]=1;
        for(int j=i-1;j>=1;j--){
            if(arr[j]<arr[i]){
                dp2[i]=max(dp2[i],dp2[j]+1);
            }
        }
        b=max(b,dp2[i]);
    }
    cout<<b<<endl;
}
int main(){
    INPUT();
    //calc();
    solve();
    return 0;
}
View Code

 



200分代码O(nlogn)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int arr[maxn],n;
int dp1[maxn],dp2[maxn];
void INPUT(){
    while(cin>>arr[++n]);
    n--;
}

void solve(){
    //sort(arr+1,arr+1+n);
    int len1=1;
    int a=0;
    dp1[len1]=arr[1];
    for(int i=2;i<=n;i++){
        //cout<<dp1[len1]<<" ";
        if(arr[i]<=dp1[len1]){
            dp1[++len1]=arr[i];
        }else{
            int p=upper_bound(dp1+1,dp1+1+len1,arr[i],greater<int>())-dp1;
            dp1[p]=arr[i];
        }
    }
    cout<<len1<<endl;
    
    int len2=1;
    dp2[len2]=arr[1];
    for(int i=2;i<=n;i++){
        if(arr[i]>dp2[len2]){
            dp2[++len2]=arr[i];
        }else{
            int p=lower_bound(dp2+1,dp2+1+len2,arr[i])-dp2;
            dp2[p]=arr[i];
        }
    }
    cout<<len2<<endl;
}
int main(){
    INPUT();
    //calc();
    solve();
    return 0;
}
View Code

 

 

 

posted @ 2021-10-20 11:00  ZangYiDe  阅读(284)  评论(0)    收藏  举报