P1020 导弹拦截 O(nlogn)做法

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是 \(\le 50000\)的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入格式

1行,若干个整数(个数 \(\le 100000\))

输出格式

2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

第一问就是求一个最长不升子序列。
第二问根据Dilworth定理就是求一个最长上升子序列

每一个任务我们都可以\(n^2\)地完成。
我们在这基础上可以优化一下,以第一个子问题为例,用\(f[i]\)表示\(dp\)值为\(i\)的最大的高度。然后在我们更新\(dp[x]\)时,只需要找到最大的\(f[i]\),这时\(dp[x] = i + 1\)
为什么呢?考虑如果有两个导弹下标分别为a,b(都在i前),如果a不仅比b高,而且\(dp[a] > dp[b]\),那么相对a来说,b对于\(dp[i]\)是不会有贡献的。
并且,通过观察我们发现\(f\)数组的值是单调的,所以我们可以二分找到我们需要的\(f[i]\)

代码如下:

#include<bits/stdc++.h>
using namespace std;

int dp1[100010],dp2[100010],f[100010];
int a[100010];
int main(){
    int tot = 0;
    while(scanf("%d",&a[++tot]) == 1);
        f[0] = max(f[0],a[tot]);
    --tot;
    for(int i = 1; i <= tot; ++i){
        int l = 0,r = tot;
        while(l < r){
            int mid = (l + r + 1) >> 1;
            if(f[mid] >= a[i]) l = mid;
            else r = mid - 1;
        }
        dp1[i] = l + 1;
        f[dp1[i]] = max(f[dp1[i]],a[i]);
    }
    memset(f,0x3f,sizeof(f));
    for(int i = 1; i <= tot; ++i){
        int l = 0,r = tot;
        while(l < r){
            int mid = (l + r + 1) >> 1;
            if(f[mid] < a[i]) l = mid;
            else r = mid - 1;
        }
        dp2[i] = l + 1;
        f[dp2[i]] = min(f[dp2[i]],a[i]);
    }
    int ans1 = 0,ans2 = 0;
    for(int i = 1; i <= tot; ++i){
        ans1 = max(ans1,dp1[i]);
        ans2 = max(ans2,dp2[i]);
    }
    cout << ans1 << endl << ans2 << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/FoxC/p/11351110.html

时间: 2024-10-06 10:43:24

P1020 导弹拦截 O(nlogn)做法的相关文章

【题解】P1020 导弹拦截

[题解]P1020 导弹拦截 从n^2到nlogn 第二问就是贪心 第一问: 简化题意:求最长不下降子序列 普通n^2: 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); cout << f[n]; 另一种n^2级,可能快一点点(还没交,不知对不对) f[0] = 1; for (int i = 1; i <= n;

codevs1044 拦截导弹==洛谷 P1020 导弹拦截

P1020 导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若干个正

p1020导弹拦截

传送门 P1020导弹拦截 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若

2015 UESTC Training for Dynamic Programming N - 导弹拦截(LIS (nlogn))

N - 导弹拦截 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都要高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭,并观测到导弹依次飞来的高度,请计算这套系统最多能拦截多少导弹,同时,司令部想知道拦截下来的导

P1020 导弹拦截 - 序列DP

传送门 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮 弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若干个整数(个数少于

洛谷 P1020 导弹拦截 【最长上升子序列】 || 【线段树】

题目链接:https://www.luogu.org/problemnew/show/P1020 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹

P1020 导弹拦截

题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若干个整数(个数少于10000

[ luogu ] P1020 导弹拦截

题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若干个正整数最多100个. 输

P1020 导弹拦截 Dilworth

题目: 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入导弹依次飞来的高度(雷达给出的高度数据是不大于50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统. 输入输出格式 输入格式: 一行,若干个整数(个数少于1