题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出格式
输入格式:
一行,若干个整数(个数少于100000)
输出格式:
2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出样例
输出样例#1:
6 2
正解:
第一问:加个‘-’,为最长不下降子序列
nlogn做法:用len[i]表示长度为i的最长不下降子序列的最小高度
考虑新加进来一个元素h[i],如果h[i]>=目前最长的子序列的最小高度,更新
如果不是,考虑用它去更新其他值,
用它替换掉第一个比他大的长度,保证最优
第二问:因为每一发导弹都是需要被拦截的,所以如果之前的系统能够拦截当前导弹,就拦截
否则在新开一个系统。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<queue> 5 #include<algorithm> 6 #include<cstring> 7 #define ll long long 8 #define inf 2147483600 9 #define DB double 10 using namespace std; 11 inline int read() 12 { 13 int x=0,w=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch==‘-‘) w=-1;ch=getchar();} 15 while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar(); 16 return x*w; 17 } 18 int n,h[100010],len[100010],cnt; 19 //len[i]长度为i的最长不下降子序列的最小高度 20 void work() 21 { 22 for(int i=1;i<=n;++i) h[i]=-h[i]; 23 memset(len,0,sizeof(len)); 24 len[1]=h[1];cnt=1; 25 for(int i=2;i<=n;++i) 26 { 27 bool fg=1; 28 for(int j=1;j<=cnt;j++) 29 if(len[j]>=h[i]) 30 { 31 len[j]=h[i];fg=0;break; 32 } 33 if(fg){cnt++;len[cnt]=h[i];} 34 } 35 printf("%d",cnt); 36 } 37 int main() 38 { 39 n=1; 40 while(scanf("%d",&h[n])!=EOF) h[n]=-h[n],n++; 41 n--; 42 len[++cnt]=h[1]; 43 for(int i=2;i<=n;++i) 44 { 45 if(h[i]>=len[cnt]) len[++cnt]=h[i]; 46 else{ 47 int pos=upper_bound(len+1,len+cnt+1,h[i])-len; 48 len[pos]=h[i]; 49 } 50 } 51 printf("%d\n",cnt); 52 work(); 53 return 0; 54 }
人生还需几分运气,但这不是全部。