【转】关于LIS和一类可以用树状数组优化的DP 预备知识
原文链接 http://www.cnblogs.com/liu-runda/p/6193690.html
- 预备知识
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 预备知识的更多相关文章
- [noip科普]关于LIS和一类可以用树状数组优化的DP
预备知识 DP(Dynamic Programming):一种以无后效性的状态转移为基础的算法,我们可以将其不严谨地先理解为递推.例如斐波那契数列的递推求法可以不严谨地认为是DP.当然DP的状态也可以 ...
- 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 ...
- Codeforces 946G Almost Increasing Array (树状数组优化DP)
题目链接 Educational Codeforces Round 39 Problem G 题意 给定一个序列,求把他变成Almost Increasing Array需要改变的最小元素个数. ...
- 【eJOI2020】考试(dp & 树状数组优化)
Description \(n\) 个正整数排成一列,每个位置 \(i\) 有一个初始值 \(A_i\) 以及目标值 \(B_i\). 一次操作可以选定一个区间 \([l, r]\),并将区间内所有数 ...
- 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 ...
- Codeforces 909 C. Python Indentation (DP+树状数组优化)
题目链接:Python Indentation 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现.现在有一种简化版的Python,只有两种语句: (1)'s'语句:Simple ...
- Codeforces 909C Python Indentation:树状数组优化dp
题目链接:http://codeforces.com/contest/909/problem/C 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现. 现在有一种简化版的Pytho ...
- BZOJ3594: [Scoi2014]方伯伯的玉米田【二维树状数组优化DP】
Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...
- bzoj 1106 [POI2007]立方体大作战tet 树状数组优化
[POI2007]立方体大作战tet Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 821 Solved: 601[Submit][Status][ ...
随机推荐
- RHEL5.6配置本地yum源
试验环境:RedHat Enterprise Linux 5.6(虚拟机) 一.挂载镜像 配置yum源第一步需要挂载镜像,或者直接复制操作系统的光盘文件至操作系统目录中. 挂载镜像命令如下: moun ...
- 实现字符串的查找和替换 分类: c/c++ 2014-10-09 22:33 469人阅读 评论(0) 收藏
在字符串中查找目标字符串并将其替换为指定字符串,返回替换的次数.接口为 int find_str_replace(char *&str,const char *find_str,const c ...
- Android推送服务(1)几种实现方式
1.几种常见的解决方案实现原理 1)轮询(Pull)方式:应用程序应当阶段性的与服务器进行连接并查询是否有新的消息到达,你必须自己实现与服务器之间的通信,例如消息排队等.而且你还要考虑轮询的频率,如果 ...
- Windows 7操作系统下PHP 7的安装与配置(图文详解)
前提博客 Windows 7操作系统下Apache的安装与配置(图文详解) 从官网下载 PHP的官网 http://www.php.net/ 特意,新建这么一个目录 ...
- DEV—【GridControl 按钮列无法触发点击事件解决方案】
需要在按钮列的OptionColumn属性栏中找到下面两个属性,并且改为True AllowEdit=True,AllowFocus=True.
- div 弹出 居中
function show_tc_conv(){var x=jq13(window).width()/2;var y=jq13(window).height()/2; var div_w=jq13(& ...
- AJPFX总结面向对象思想设计原则
面向对象思想设计原则 A.单一职责原则 其实就是开发人员经常说的”高内聚,低耦合” 也就是说,每个类应该只有一个职责,对外只能提供一种功能,而引起类变化的原 ...
- SpringMvc如何将Url 映射到 RequestMapping (二)
昨天简单分析了Springmvc 中 RequestMapping 配置的url和请求url之间的匹配规则.今天详细的跟踪一下一个请求url如何映射到Controller的对应方法上 一.入口 org ...
- spark集群启动步骤及web ui查看
集群启动步骤:先启动HDFS系统,在启动spark集群,最后提交jar到spark集群执行. 1.hadoop启动cd /home/***/hadoop-2.7.4/sbinstart-all.sh ...
- swift 即使不使用oc的动态派发机制也应该借鉴isa类型识别机制
目前的消息派发机制真的很鸡肋. 简直是一堆狗屎. 类型信息中包含所有需要动态派发的函数:这个包含两类:类和protocol: 在编译时,首先搜索动态派发列表: 动态派发列表没有,在搜索静态派发列表: ...