From c6adc2b6e5af8aa987d7991ac7e8ef61d9b09de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B5=B7?= <10402852@qq.com> Date: Wed, 6 Mar 2024 13:32:24 +0800 Subject: [PATCH] 'commit' --- TangDou/AcWing_TiGao/T1/LIS/LIS+LCS专题.md | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/TangDou/AcWing_TiGao/T1/LIS/LIS+LCS专题.md b/TangDou/AcWing_TiGao/T1/LIS/LIS+LCS专题.md index a1c35b5..507c62e 100644 --- a/TangDou/AcWing_TiGao/T1/LIS/LIS+LCS专题.md +++ b/TangDou/AcWing_TiGao/T1/LIS/LIS+LCS专题.md @@ -275,6 +275,55 @@ int main() { **[$AcWing$ $1010$. 拦截导弹](https://www.acwing.com/problem/content/1012/)** +**数组说明** +$q[],ql$:已经创建了$ql$套导弹系统,$q[i]$中记录的是第$i$套导弹系统的最大拦截高度 + +**算法思路** +- 在已有的所有导弹拦截系统中找到大于当前高度,并且最小的那个,把当前导弹用这套拦截系统进行拦截 +- 如果找不到这样的拦截系统,说明当前所有拦截系统的最小拦截高度都小于当前导弹,都无法利用,必须新开一个拦截系统。 +- 只有前面所有拦截系统的最后一个拦截高度,都小于当前高度时,才会创建新的,所以,后面的拦截系统,它的尾巴值应该是最大的 + +**举栗子**: +$q[0]:5$ +$q[1]:6$ +现在来了一个高度=$4$,根据上面的原则,应该放到$q[0]$里,修改$q[0]=4$ +$q[0]:4$ +$q[1]:6$ +原来的数组是单调上升的,修改后也依然是单调上升的。 + +再比如: +$q[0]:4$ +$q[1]:6$ +$q[2]:7$ +现在来了一个$a[i]=5$,我们肯定要修改$q[1]=5$,变为: + +$q[0]:4$ +$q[1]:5$ +$q[2]:7$ +原来的数组是单调上升的,修改后也依然是单调上升的。 + +既然有这个规律,那么就可以使用二分快速查找大于等于$a[i]$的位置$p$了: + +```cpp {.line-numbers} + // 第一问 + for (int i = 0; i < n; i++) { + f[i] = 1; + for (int j = 0; j < i; j++) + if (a[i] <= a[j]) // 如果前面的比当前的大,说明是不升序列 + f[i] = max(f[i], f[j] + 1); + res = max(res, f[i]); + } + // 第二问 + for (int i = 0; i < n; i++) { + int p = lower_bound(q, q + ql, a[i]) - q; + if (p == ql) // 如果没有找到可以接在后面的导弹拦截系统,那么需要创建一套新的拦截系统 + q[ql++] = a[i]; + else + q[p] = a[i]; // 否则就直接接到找到的第k套拦截系统的后面,那么,第k套拦截系统的最后一个拦截高度=q[k]=h[i] + } + // 输出最长不升序列长度,即:最多能拦截的导弹数 + printf("%d\n%d\n", res, ql); +``` **[$AcWing$ $187$. 导弹防御系统](https://www.acwing.com/problem/content/189/)**