这道题,分为两部分:这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
这道题就是最长下降子序列和最长上升子序列,并且得%50是用o(n方)的复杂度,后%50就是o(n logn)
#第一部分:
可以先用一个dp存,dp留大不留小,最后输出len
首先输入要用while(cin>>a[i]),最后记得i--。
第一个不用去比较a[i],因为现在dp中啥也没有,也就是
dp[1]=a[1];
注意!后面循环就得从2开始了
首先去看这个dp的最后一个(dp[len])和a[i]去比较,如果小于就直接在dp[len]=a[i];前面记得len++;总之就是下面代码:
if(dp[len]>=a[i]){
len++;
dp[len]=a[i];
continue;
}
然后不是接不了了么,就用二分完成。
举个例子
dp[i]为:10 9 8 7 6 5 5 4 3
要插入9,所以要把8换成9
总之就是一个二分,看他插在哪里
long long l=1,r=len,pos=0;
while(l<=r){
int mid=(l+r)/2;
if(dp[mid]==a[i]) l=mid+1;//不替换
if(dp[mid]<a[i]){//替换,看看还有没有更好的
pos=mid;
r=mid-1;
}
if(dp[mid]>a[i]) l=mid+1;//不插
}
dp[pos]=a[i];
最后第一部分接完成了
记得是输出len
第二部分就是利用一个dilworth定理,可以去了解一下,言归正传,所以按这个定理,这个问题就成为了问数据里有几个最长上升子序列,还是第一问的思路,用二分,代码如下:
memset(dp,0,sizeof(dp));//一定要清空
long long cnt=0,k=0;
len=0;
for(int i=2;i<=n;i++)
if(dp[len]<a[i]){
len++;
dp[len]=a[i];
continue;
}
long long l=1,r=len,pos=0;
while(l<=r){
int mid=(l+r)/2;
if(dp[mid]<a[i]) l=mid+1; //不替换
if(dp[mid]>=a[i]){//替换,看看还有没有更好的
pos=mid;
r=mid-1;
}
}
dp[pos]=a[i];
当然,还是输出len
最后把这两问连起来,这题就结束了