main
黄海 1 year ago
parent a6463174fb
commit 0f1816c10a

@ -55,26 +55,13 @@
问题一 套用 $LIS$ 模型即可求解。由 $Dilworth$ 定理,问题二等价于 另一个 $LIS$ 长度
#### 贪心法
对于每个数,既可以把它接到已有子序列后面,也可以建立一个新序列。要使子序列数最少,应尽量不建立新序列。此外,应让每个子序列的末尾尽可能大,这样能接的数更多。因为一个数若能接到小数后面,必然能接到大数后面,反之则不成立。根据这些想法,可总结出如下贪心流程:
![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202403041334201.png)
>从前往后扫描每个数,对于当前数
> - 若现有子序列的结尾都小于它,则创建新子序列
> - 否则,将它放到结尾大于等于它的最小数后面
我们用两个贪心的证明方法来证明:
![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202403041346994.png)
##### 证明 (最优解 = 贪心解)
![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202403041346474.png)
假设存在一个最优解,他在考虑第 $i$ 个数放入的下降子序列组中,选择了贪心解方案的后面的一个位置
具体如图所示:(绿色部分,更新了$q[i+1]$后为保证递增顺序,交换了$q[i]$和$q[i+1]$,这一步省略了)
![](https://cdn.acwing.com/media/article/image/2021/06/03/55909_ffc9a769c4-IMG_43104A5A0544-1.jpeg)
可以观察到,该最优策略使得当前局面差于贪心策略,即能接在$(q[i],q[i+1])$范围的子序列少了一个,即 **贪心解** ≤ **最优解**
同理可证,**最优策略** 在考虑第 $i$ 个数放入的下降子序列组中,选择了贪心解方案的后面的第 $k$ 个位置 也有结论 **贪心解** ≤ **最优解**
此外,由于**贪心解** 是 **合法解**,所以必然 **贪心解** ≥ **最优解**
于是有 **贪心解** = **最优解**
#### $Code$
朴素作法 $O(N^2)$

@ -0,0 +1,37 @@
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n;
int h[N], f[N], q[N];
int main() {
string line;
getline(cin, line);
stringstream ssin(line);
while (ssin >> h[n]) n++;
int res = 0, cnt = 0;
for (int i = 0; i < n; i++) {
f[i] = 1;
for (int j = 0; j < i; j++)
if (h[i] <= h[j])
f[i] = max(f[i], f[j] + 1);
res = max(res, f[i]);
int k = 0;
while (k < cnt && q[k] < h[i]) k++;
if (k == cnt)
q[cnt++] = h[i];
else
q[k] = h[i];
}
printf("%d\n", res);
printf("%d\n", cnt);
return 0;
}

@ -86,3 +86,6 @@ int main() {
**[题解传送门](https://www.cnblogs.com/littlehb/p/17510484.html)**
### 五、关键字
- 魔改$LIS$
- 最大上升子序列和
Loading…
Cancel
Save