P1020 导弹拦截
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是 \le 50000≤50000 的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出格式
输入格式:
11 行,若干个整数(个数 \le 100000≤100000 )
输出格式:
22 行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出样例
说明
为了让大家更好地测试n方算法,本题开启spj,n方100分,nlogn200分
每点两问,按问给分
题解:
这个题的写法是从后往前来一个最长的非递减子序列,求出一个系统能拦截多少导弹,然后然后正常的求正向的上升子序列,而这个上升子序列就是我们需要的导弹数目,此处是本题的难点,需要想明白为什么。
简单解释一下就是说(主要是自己也不知道该如何解释),最长的上升子序列中每多一个数字,我们需要新添一个系统,因此系统数目+1;
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=1e5+10; 4 const int INF=0x3f3f3f3f; 5 int a[MAXN],b[MAXN]; 6 int dp[MAXN],DP[MAXN]; 7 int main() 8 { 9 int n=0; 10 while(~scanf("%d",&a[n++])); 11 int k=0; 12 for(int i=n-1;i>=0;i--) 13 { 14 b[k++]=a[i]; 15 } 16 fill(DP,DP+k,INF); 17 for (int i = 0; i <k ; ++i) { 18 *upper_bound(DP,DP+k,b[i])=b[i]; 19 } 20 printf("%d\n",lower_bound(DP,DP+k,INF)-DP-1); 21 fill(dp,dp+n,INF); 22 for (int i = 0; i < n; ++i) 23 { 24 *lower_bound(dp,dp+n,a[i])=a[i]; 25 } 26 printf("%d\n",lower_bound(dp,dp+n,INF)-dp ); 27 return 0; 28 }