zoukankan      html  css  js  c++  java
  • 动态规划习题分类题解 (202103)

    动态规划习题分类题解 (202103) - 4. LIS相关

    [CF269B]GreenhouseEffect

    Description

    给出 N 个植物,每个植物都属于一个品种,共计 m 个品种,分落在不同的位置上(在一个数轴上,而且数轴是无限长度的),保证读入的位置是按照升序读入的。
    现在我们可以进行一个操作:取任意一个位置上的植物,移动到任意一个没有植物的位子上去。
    问我们最少进行多少次操作,能够使得从左到右,是按照品种升序排列的(1 ~ m)(单调不降),而且每种植物都相邻。

    Solution

    求一下最长非严格上升子序列即可

    [CF486E]LISofSequence

    Description

    给定一个数列,对于每个元素,问它属于以下哪一类:必须在最长上升子序列中;可能在最长上升子序列中,不可能在最长上升子序列中。

    Solution

    求每个元素开头和结尾的最长上升子序列长度 (f[i])(g[i])
    如果 (f[i]+g[i]-1<ans),其中 (ans) 是整个序列的最长上升子序列,则 (i) 不可能在最长上升子序列中
    如果存在 (j),使得 (f[i]=f[j], g[i]=g[j]),则 (i) 不在所有的最长上升子序列中
    否则,(i) 一定在所有的最长上升子序列中

    [CF1257E]TheContest

    Description

    有三个序列 (a.b.c),每次操作可以把一个序列中的一个数移动到另一个序列中,问最少操作几次后,可以使得 (a) 序列里的所有数小于 (b) 里面的所有数,(b) 里面的小于 (c) 里面的。

    Solution

    从结果倒过来考虑,假设三个序列各自有序,那么可以保持不动的部分就是三个序列连在一起的最长上升子序列

    [CF1296E2]StringColoring(hardversion)

    Description

    给定字符串,每个位置染上一种不大于 n 的颜色,相邻位置如果颜色不同则可以交换位置,要求交换若干次后按字典序排序。求颜色数最少的染色方案。

    Solution

    每个字母最后被换到的位置是确定了
    一路上所有的字母得跟他颜色不同
    于是逆序对的颜色都是不同的,否则无要求
    (f[i]) 表示 ([i,n]) 中 i 开头的最长下降子序列长度,那么我们将 (f[i]) 作为 i 的颜色,就可以保证所有逆序对颜色不相同

    如果逆序对 i,j 颜色相同,那么我们可以构造 i->j 的转移,使得 $f[j]$ 增大,矛盾
    现在问题是怎么求每个位置开头的 LDS 长度 一个显然的暴力是,倒序扫描,找每个最近的更小字母位置 但与其记录字母位置,不如直接记录每个更小字母已经有过的最大长度,然后直接续上

    [CF1367F1]FlyingSort(EasyVersion)

    Description

    给定一个序列,可以进行若干次操作,每次将一个数调到开头或者调到最后。求将序列排序的最小次数。保证序列中数字互不相同。

    Solution

    先离散化成排列,然后发现,不动的数就是原排列中的最长连续上升子序列。
    充分性是显然的。
    考虑必要性,对于任意一种操作方案,那些没有被操作的数必然会构成原排列中的最长连续上升子序列,因为这些数没被移动他们最后必然是连在一起的。

    [CF1437E]MakeItIncreasing

    Description

    给定一个数列,其中一些元素固定,另一些元素可以修改。要求修改最少的元素使得这个序列变成严格单增的序列。

    Solution

    首先通过 (a_i leftarrow a_i-i) 将原序列变为非严格单增的序列。
    固定元素将原序列分割成了若干段,每段内求一下 LCS,剩下的就是需要移动的。注意,如果超出了左右两侧的固定元素限制的值域,那么这个元素也必须被移动。

    [HAOI2006]数字序列

    Description

    现在我们有一个长度为n的整数序列A。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。求在改变的数最少的情况下,每个数改变的绝对值之和的最小值。
    (nleq 35000),保证数据随机

    Solution

    第一问很容易,只需要令 (b_i=a_i-i),然后跑最长不下降子序列即可
    下面考虑第二问,令 (f[i]) 表示前 (i) 个数构成的数列要变成单调上升需要改动的最小幅度
    (a_i,a_j, i<j) 满足 (a_j-a_i geq j-i),则 ([i,j]) 中一定存在一个 (k),使得 (a[idots k]) 都变成 (a[i])(a[k+1dots j]) 都变成 (a[j]),整个序列上升并且花费的代价最小,暴力枚举 (j,k) 来转移,时间复杂度为 (O(n^3))

    证明可以通过任意构造一种最优解形态,然后通过代价不变的转化使其变化为上述形态

    考虑转移到 (f[i]) 的决策点 (j<i) 要求第一问中的 (g[j]+1=g[i]),因此转移点的总数是 (O(n))(O(nsqrt n)) 量级的,且 (w) 的区间期望为 (O(sqrt n)),总体复杂度估计为 (O(nsqrt n))(O(n^2)) 之间
    在数组前后额外添加最大最小值,可以提供类似于超级源汇的功能

    [HAOI2007]上升序列

    Description

    给定序列 (S),有 (m) 次询问,每次要求输出下标字典序最小的长度为 (l_i) 的上升序列

    Solution

    考虑设 (f[i]) 表示从 (i) 发出的最长上升子序列的长度,倒序转移
    转移时,在使得 (f[i]) 最大的情况下,使得 (i) 尽量小,即可使得字典序最小
    每次询问时,检查是否有 (f[i]=l),如果没有则直接判定无解
    否则,从头开始,利用已经预处理出的 (f[i]) 数组,贪心地找出一个下标字典序最小的上升序列即可

  • 相关阅读:
    第七章之main函数和启动例程
    第一章之系统调用、库函数、内核函数区别
    unp第七章补充之socket tcp 产生 rst响应的情况
    unp第七章补充之TCP半开连接与半闭连接
    Qt 布局管理器
    Qt setMargin()和setSpacing() 的含义
    工作感悟
    关于数组数据常用的技巧
    正则表达式练习
    call/apply应用-对象使用原型链上的方法
  • 原文地址:https://www.cnblogs.com/mollnn/p/14553661.html
Copyright © 2011-2022 走看看