原文链接 http://www.cnblogs.com/liu-runda/p/6193690.html

  1. 预备知识

    DP(Dynamic Programming):一种以无后效性的状态转移为基础的算法,我们可以将其不严谨地先理解为递推。例如斐波那契数列的递推求法可以不严谨地认为是DP。当然DP的状态也可以是二维/三维的,某一维的含义也不仅仅是指某个数列的第几项。

    树状数组(BIT or fenwick tree):一种高效地动态维护一个序列并动态求取前缀和的数据结构。修改某个元素/求一次前缀和的时间复杂度均为O(logn)

  2 LIS

    好了现在假设你们都会打树状数组了(如果不会的话,baidu一发吧!顺便把线段树也自学了吧!如果学不会树状数组只把线段树自学了也成因为好像并没有树状数组能干而线段树干不了的事情),让我们做一道例题练习一下吧!。

    给出一个长度为n的序列,求LIS长度(LIS,longest increasing sequence,最长上升子序列,子序列定义为从原序列取出的一些未必相邻但保持原先的相对顺序的数,上升子序列满足子序列中前一个数严格小于后面的数)

    50% n<=5000,100% n<=50000

    50%的数据其实并没有用到树状数组。

    O(n^2)的LIS算法:定义f[i]为强制以第i项结尾时的LIS长度。那么从1到n依次求出每个f[i],f[i]可以由f[1...i-1]推出。

    好了,现在假设你们都会写50分了。我们考虑把算法优化到能跑50000

    首先离散化,将原先的数字对应到1-tot(tot为出现过的数值种类),例如10,10,20,15变成1,1,3,2

    那么我们定义g[i]为以数值i结尾的LIS长度,并从左向右扫描原数组,同时维护g数组。扫描1,1,3,2时,g数组变化如下:(未出现的项的值为0)

      a.g[1]=1

      b.g[1]=1

      c.g[1]=1,g[3]=2

      d.g[1]=1,g[2]=2,g[3]=2

    YY一下我们怎样用g数组完成DP。

    接下来我们需要一种数据结构支持单点修改(只增不减)和前缀最大值查询。

    首先来一个逗比分块写法维护g数组:将g均分成sz块,维护每一块的最大值。修改可以O(1)完成,前缀最大值查询可以将整块整块的部分用每一块的最大值求,零散部分暴力扫一遍。sz取在sqrt(n)附近的时候效率最高。总时间复杂度O(nsqrt(n)),自信AC。

    如果n<=233333?

    我们可以树状数组维护g数组。原始的树状数组改造后可以支持单点修改(只增不减)和前缀最大值查询。把树状数组的加法换成取最大值,YY一下。

    最后整个g数组的最大值就是答案。

  3. LCS

    好了,现在假设你们都会nlogn的LIS,让我们来一道例题练习一下吧!

    uva10635 Prince and Princess(数据范围是我口胡的)

    给出两个1~n的排列(一个1~n的排列中,1-n每个数字出现一次,不重复出现),求LCS(最长公共子序列)长度。50%的数据保证第一个排列为1,2,3,...n按顺序递增的。

    n<=233333

    50%数据是第二个排列的LIS。很好50分到手。

    下面设想一下,把数字重新编号,LCS长度不变。例如,两个序列为1,2,3; 3,2,1.那么a,b,c;c,b,a的答案是和它一样的。那么把数字编号为数字也是可以的。

    例如这两个数据:

    (1)

    4

    1 2 3 4

    2 3 4 1

    (2)

    4

    4 3 2 1

    3 2 1 4

    它们的答案是相同的。因为在求解LCS时,我们只关注两个序列某两个下标处的数值是否相同,重新编号没有改变“对应下标位置的数相同”的信息。

    那么我们把一个序列重编号为1,2,3...n,对另一个序列也用同样的对应关系重编号(即把第二个序列中每个数改成这个数在第一个序列中出现的下标),跑LIS,自信AC。

  4. more about LCS

    接下来我们分兵奇袭,用另一条思路得出刚才例题lcs的另一个nlogn做法。

    首先自己yy一下LCS的O(n^2)算法。它的状态定义为f[i][j]表示允许使用第一个序列的前i个元素,第二个序列的前j个元素(其中第i个,第j个元素不要求必须使用)

    接下来我们修改状态定义(这种事情在优化DP时需要经常干)使得它能优化到nlogn.

    新的状态中,f[i][j]表示允许使用第一个序列的前i个元素,第二个序列的前j个元素(其中第一个序列第i个元素不必须使用,第二个序列第j个元素必须使用

    于是我们把原先的DP改成分层的过程,考虑从f[i-1][]求出f[i][],那么这两个数组最多有一个位置不同(只有以第一个序列的第i个元素结尾的答案会发生改变)。

    那么我们动态维护这个数组就可以了。假如第一个序列中第i个元素在第二个序列中出现在第k个位置,那么修改f[k]即可(这里已经干掉了第一维)。

    f[k]等于什么?等于f[1...k-1]的最大值+1,因为在LCS中前一项一定是第二个序列前面k-1的项中的一项(如果已经是第一项,没有前一项?边界自己处理一下我就不(懒得)写了)。

    于是还是树状数组前缀最大值,只增不减的单点修改。

    事实上,这个算法只要保证匹配上的位置不多即可。因此1-n每个数字出现5次也是能写的。

    http://www.lydsy.com/JudgeOnline/problem.php?id=1264 bzoj1264基因匹配

  5。more about BIT&DP

    二维树状数组也是可以拿来优化DP的 http://www.lydsy.com/JudgeOnline/problem.php?id=3594  方伯伯的玉米田

    坐标系可以转...http://www.lydsy.com/JudgeOnline/problem.php?id=2131  免费馅饼

    和树状数组没关系的傻逼题 http://www.lydsy.com/JudgeOnline/problem.php?id=4300

    2016.12.31update:终于想到了一道noip题NOIP2012摆花 http://cogs.pro/cogs/problem/problem.php?pid=1270

  6. 巩固练习一下LIS

    http://www.lydsy.com/JudgeOnline/problem.php?id=3173

    http://www.lydsy.com/JudgeOnline/problem.php?id=4660

由于我太弱,所以这里的例题比较少...虚心求dalao们在评论区提供例题。

【转】关于LIS和一类可以用树状数组优化的DP 预备知识的更多相关文章

  1. [noip科普]关于LIS和一类可以用树状数组优化的DP

    预备知识 DP(Dynamic Programming):一种以无后效性的状态转移为基础的算法,我们可以将其不严谨地先理解为递推.例如斐波那契数列的递推求法可以不严谨地认为是DP.当然DP的状态也可以 ...

  2. HDU - 5542 The Battle of Chibi(LIS+树状数组优化)

    The Battle of Chibi Cao Cao made up a big army and was going to invade the whole South China. Yu Zho ...

  3. Codeforces 946G Almost Increasing Array (树状数组优化DP)

    题目链接   Educational Codeforces Round 39 Problem G 题意  给定一个序列,求把他变成Almost Increasing Array需要改变的最小元素个数. ...

  4. 【eJOI2020】考试(dp & 树状数组优化)

    Description \(n\) 个正整数排成一列,每个位置 \(i\) 有一个初始值 \(A_i\) 以及目标值 \(B_i\). 一次操作可以选定一个区间 \([l, r]\),并将区间内所有数 ...

  5. HDU 5542 - The Battle of Chibi - [离散化+树状数组优化DP]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5542 Problem DescriptionCao Cao made up a big army an ...

  6. Codeforces 909 C. Python Indentation (DP+树状数组优化)

    题目链接:Python Indentation 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现.现在有一种简化版的Python,只有两种语句: (1)'s'语句:Simple ...

  7. Codeforces 909C Python Indentation:树状数组优化dp

    题目链接:http://codeforces.com/contest/909/problem/C 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现. 现在有一种简化版的Pytho ...

  8. BZOJ3594: [Scoi2014]方伯伯的玉米田【二维树状数组优化DP】

    Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...

  9. bzoj 1106 [POI2007]立方体大作战tet 树状数组优化

    [POI2007]立方体大作战tet Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 821  Solved: 601[Submit][Status][ ...

随机推荐

  1. import android.support.v4或者import android.support.v7提示导入错误解决办法

    转自:  http://blog.csdn.net/forandever/article/details/37655139 在使用Eclipse开发andriod程序时,程序中提示import and ...

  2. RMAN-06564错误的原因及解决办法

    今日在进行数据库恢复时,遭遇RMAN-06564错误,如下: RMAN> restore spfile from autobackup; Starting restore at 01-NOV-1 ...

  3. jmeter(十五)Jmeter默认报告优化

    一.本文目的: 之前写了两篇文章搭建持续集成接口测试平台(Jenkins+Ant+Jmeter)和ANT批量执行Jmeter脚本,功能实现上都没有什么问题,但是最后生成的报告有一点小问题,虽然不影响使 ...

  4. C++中的数学函数汇总

    math.h 数学函数库,一些数学计算的公式的具体实现是放在math.h里,具体有: 1 三角函数 double sin (double); double cos (double); double t ...

  5. idea 部署struts所遇到的问题\

    1.org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter 加载失败 解决方法:下载struts2 的源码包,然后将D:\ ...

  6. 【分享】iTOP-iMX6UL开发板驱动看门狗 watchdog 以及 Linux-c 测试例程

    iTOP-iMX6UL开发板看门狗测试例程,iTOP-iMX6UL 开发板的看门狗驱动默认已经配置,可以直接使用测试例程. 版本 V1.1:1.格式修改:2.例程修改完善,其中增加喂狗代码.1 看门狗 ...

  7. flutter 实现圆角头像的2种方法

    圆角头像在开发中应用太普遍了,我总结了2种实现方法,分享给大家 方法一: 使用Container组件的decoration可以实现 Container( width: 40, height: 40, ...

  8. 20181019 记录 window.setTimeout('dofunction()',2000); - layui form 表单提交 事件 - F11全屏 事件 window.onresize

    1 延时事件 window.setTimeout('dofunction()',2000); 函数外面要有引号 如果没有引号 就不能延时执行 应该是内容进行eval,所以外层不是传递字符串的话,外层函 ...

  9. pavenet资源

    网络结构:http://www.cnblogs.com/fariver/p/7449563.html 源码:https://github.com/sanghoon/pva-faster-rcnn 训练 ...

  10. 通俗易懂的Redux了解下

    Redux真的让我脑仁疼,感觉有点搞不定他,因为对我而言太抽象了.所以我用通俗易懂地方法去思考Redux,感觉能够理解了. 本文要点: action 配置行为 store.dispatch(actio ...