洛谷 P1020 导弹拦截

题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是≤50000 \le 50000≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入格式 111行,若干个整数(个数≤100000 \le 100000≤100000)
输出格式 222行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出样例 输入 #1
复制
389 207 155 300 299 170 158 65
输出 #1
复制
6
2
说明/提示 为了让大家更好地测试n方算法,本题开启spj,n方100分,nlogn200分
每点两问,按问给分

用这题复习一下LIS问题
前一百分:n^2dp

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m; 
int f[100005];
int a[100005];
inline int read(){
 int x=0,f=1;
 char ch=getchar();
 while(ch<'0'||ch>'9'){ch=getchar();if(ch=='-')f=-1;}
 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 return x*f; 
}
int main(){
 while(cin>>a[++n]);n--; 
 int minn=1,zu=1;
 f[1]=1;//到第i位,最长子序列为f[i]
 for(int i=1;i<=n;i++) f[i]=1;
 for(int i=n;i>=1;i--){ 
  for(int j=n;j>i;j--){
   if(a[j]<=a[i]){
      f[i]=max(f[i],f[j]+1);
   }
  }
 } 
 int ans=0;
 for(int i=1;i<=n;i++){
    ans=max(ans,f[i]);
 }
 cout<<ans;
 for(int i=1;i<=n;i++) f[i]=1;
 for(int i=1;i<=n;i++){
  for(int j=1;j<i;j++){
   if(a[j]<=a[i]){
    f[i]=max(f[i],f[j]+1);
   }
  }
 }
 ans=0;
 for(int i=1;i<=n;i++){
  ans=max(ans,f[i]);
 } 
 cout<<endl<<ans;
 return 0;
 
}

前两百分,二分+贪心
在这里讲解(复习)一下lower_bound以及upper_bound
lower_bound:找出序列中第一个大于等于x的数
upper_bound:找出序列中第一个大于x的数
(啦啦啦就差个等号)
格式

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m; 
int a[100005];
int f[100005];
int ff[100005];
inline bool cmp(const int &a,const int &b){
 return a>b;
}
inline int read(){
 int x=0,f=1;
 char ch=getchar();
 while(ch<'0'||ch>'9'){ch=getchar();if(ch=='-')f=-1;}
 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 return x*f; 
}
int main(){
 while(cin>>a[++n]);n--; 
 f[1]=a[1];
 ff[1]=a[1];
 int len=1; 
 for(int i=2;i<=n;i++){
  if(a[i]<=f[len]) f[++len]=a[i];
  else{
   int p=upper_bound(f+1,f+len+1,a[i],cmp)-f;
   f[p]=a[i];
  }
 }
 cout<<len;
 len=1;
 for(int i=2;i<=n;i++){
  if(a[i]>ff[len]) ff[++len]=a[i];
  else{
   int p=lower_bound(ff+1,ff+len+1,a[i])-ff;
   ff[p]=a[i];
  }
 }
 cout<<endl<<len;
 return 0;
}
上一篇:2021-10-26


下一篇:<Linux>Shell中的条件测试