谈一下自己对动态规划的理解
做过了不少的DP题,发现了一个规律,那就是打表!找出所有满足条件的答案,不过这种枚举和一般的暴力可不一样,暴力求解的时候是每次从最初的状态开始枚举所有答案,这样一般都会造成多个数据被重复计算,极大地增加了时间上的消耗。
而动态规划是在暴力的基础上进行的优化,我们需要求出满足条件的所有答案,那么这些答案之间是否有所联系的?一般来说是有很大联系的,而动态规划就是利用答案之间的联系,求解出其他的答案。
在求解一个问题的时候,先将这个问题分解成若干个子问题,而我们往往先求出了子问题的答案。
比如:我们需要求 1 - 100 以内任意两个数之间的素数的个数,具体的操作如下。
1)我们先求出了所有长度为1的区间中含有的素数个数 。
2)随后,我们求出了所有长度为2的区间中含有的素数个数,我们在求 [ x ,x + 1] 区间内素数的个数的时候,可以将这个问题分解为求区间 [ x, x ] 和 [ x+1, x+1 ] 内的素数的个数; 由于第一步已经计算过了这两个区间内的素数个数,所以我们不需要重复计算,可以直接用上一步计算出来的答案作为这个问题的子问题的答案即可。
3).......
4)那么现在我们要求区间 [ x, x + n - 1 ] 内所有素数的个数,由于之前我们已经求出了所有区间长度在 [ 1 , n-1 ] 的区间内的素数个数,那么我们只需要让区间 [ x, x ] 和 [ x+1 , x + n -1 ] 内的素数个数相加即可(因为这个答案我们之前已经计算过了)得到我们需要的答案。
当我们完成上面的打表操作之后,我们就得到了 [ 1, 100 ] 内,任意区间的素数的个数,询问的时候,可以直接输出答案。
其实主席树的思路也和这个差不多,我们需要多个保存不同时期的线段树,以此来求出答案,因此我们利用上一次的线段树构造新的线段树,由于线段树的更新只涉及一个链(就是和更新数据有关的结点练成一条线),我们保存了上一次线段树在中没有被更新的结点,然后只需要构建需要更新的结点即可,利用了之前已经存在的数据,而不需要重新构建.。