LIS问题

发布时间 2023-07-03 22:33:02作者: smiling&weeping

Smiling & Weeping

                ----后悔没能说声再见,以至于后来有人仅似你三分,我便慌了神

 

# [NOIP1999 普及组] 导弹拦截

 

## 题目描述

 

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

 


输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

 

## 输入格式

 

一行,若干个整数,中间由空格隔开。

 

## 输出格式

 

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

 

## 样例 #1

 

### 样例输入 #1

 

```
389 207 155 300 299 170 158 65
```

 

### 样例输出 #1

 

```
6
2
```

 

## 提示

 

对于前 $50\%$ 数据(NOIP 原题数据),满足导弹的个数不超过 $10^4$ 个。该部分数据总分共 $100$ 分。可使用$\mathcal O(n^2)$ 做法通过。
对于后 $50\%$ 的数据,满足导弹的个数不超过 $10^5$ 个。该部分数据总分也为 $100$ 分。请使用 $\mathcal O(n\log n)$ 做法通过。

 

对于全部数据,满足导弹的高度为正整数,且不超过 $5\times 10^4$。

 


此外本题开启 spj,每点两问,按问给分。

 

---

 

$\text{upd 2022.8.24}$:新增加一组 Hack 数据。

题目详见:P1020 [NOIP1999 普及组] 导弹拦截 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n , num[100100] , l1[100100] , l2[100100];
 4 int main()
 5 {
 6     while(cin >> num[++n]);   
 7     int x = 0 , t = 0;
 8     int xx = 0 , tt = 0;
 9     for(int i = 1; i <= n; i++)
10     {
11         int l = 0 , r= t+1;
12         while(r - l > 1)
13         {
14             int mid = r+l >> 1;
15             if(l1[mid] < num[i]) l = mid; //单调上升
16             else
17             r = mid;
18         }
19         x = l+1;
20         if(x > t) t = x;
21         l1[x] = num[i];
22         l = 0 , r = tt+1;
23         while(r - l > 1)
24         {
25             int mid = l+r >> 1;
26             if(l2[mid] >= num[i]) l = mid; //单调不升
27             else
28             r = mid;
29         }
30         xx = l+1;
31         if(xx > tt) tt = xx;
32         l2[xx] = num[i];
33     }
34     cout << tt-1 << endl;
35     cout << t << endl;
36     return 0;
37 }

代码大致如此,有些粗糙,如果不懂随时@我