C++导弹拦截

这道题,分为两部分:这套系统最多能拦截多少导弹如果要拦截所有导弹最少要配备多少套这种导弹拦截系统

这道题就是最长下降子序列和最长上升子序列,并且得%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

最后把这两问连起来,这题就结束了

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值