分而治之-----浅谈分治算法的一些应用

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

不难发现我们通过定义一个名为Solve()的过 程,不断的对答案进行划分。从而解决了问题。 其本质是将原来的一个K小数问题,转化为了 一个统计的问题,通过对数大小的划分而解决了大 小的限制,以非常小的代价对问题进行了简化。 这给我们启发,对于一类问题,可以通过对其 的某个条件进行将询问分治从而对原问题的进行化 简而快速的解决原问题。
输入 第一行为N 接下来N行对应每条鱼的 H,Len,W,M 数据大小: N,W,H,M,Len<=106666。时限7S。 保证答案在32位有符号整形内。 input output 4 12 1115 2344 4356 5553
简单来说,这题其实就是要我们按照天数找出 一个升高长度重量都递增的一个鱼序列,重量总和 最大。 其实就是一个3维的Lis问题,不过带权了罢 了。 更一般的,把天数也作为一个参数D,我们要找 到一个序列,4维都递增。总权值最大。 貌似直接求解有点难度,我们来考虑点简单 的问题。
数据结构优化貌似走到了死胡同。 我们尝试跳出这个思维习惯,想想能不能不裸 用数据结构。 记得前面说过,分治算法在划分的过程中可以
对于限制进行划分而解决限制的条件来简化问题。
这个结论在这里的用处是什么? 条件多不要紧
我们可以依次分治!
定义Solve1(L,R) 表示计算天数状态在(L,R)内 的鱼的DP值。 我们的目标是Solve1(1,N)。 取Mid=(L+R)/2 假设我们如果解决了 Solve1(L,Mid)。我们想如何算出dp[Mid+1…R]。 考虑到dp[Mid+1….R]里的dp[i]都是可以由 dp[L…Mid]以及Dp[Mid+1..i-1]转移过来。对于 dp[Mid+1..i-1]的转移我们可以在Solve1(Mid+1,R) 进行转移。我们现在只需要考虑dp[L..Mid]向 dp[Mid+1..R]里面的转移就行了。 你发现了什么?
假设只有一维限制? 我们sort完了之后直接取每个限制里的最大值 加起来就行了。 二维?(x,y)? 按照第一维排序,依次处理,这样就能保证第 一维的限制。不难写出DP方程,记录dp[i]表示的 以I为结尾的序列最大和是多少。 dp[i]=max(dp[j]) +w[i] (y[j]<y[i]) 是平方复杂度的DP。优化? 考虑到我们取出的是 满足 y[j]<y[i] 里的最大 的 dp[j]。我们以y[j] 为关键字用树状数组维护前缀 最大值就行了。复杂度变成了O(NlogN)可以接受。
考虑区间的平衡程度决定着算法的效率,我们 将数排序。 原序列 : 1 5 3 4 5 1 2 4 排序后: 1 1 2 3 4 4 5 5 取Mid=(L+R)/2,中点值为3。 1 5 3 4 5 1 2 4 我们只要知道每个询问范围内的红点个数是否 超过K就知道他的答案应该是比3大还是3小了。
也就是说我们只需要每次确定所需要划分的区 间就可以了。 不难发现这个算法是期望O(N)的。 这个问题就被快速解决了。
这个问题有啥用? 我们来考虑问题的加强版。
给你一个N*N的矩阵,询问在以(X1,Y1)为左 上角(X2,Y2)为右下角的矩阵内的元素的第K小值。 N<=500,Q<=60000。 Input output 332 1 352 2 231 531 13332 11333
给你个数列,长度为N,现在询问他的第K小数 是什么? 数据规定: N<=3000000,K<=N。 Input Output 53 3 12345
直接排序?
sort(a+1,a+n+1); printf (a[k]); 很短?
TLE
[
这个方法为什么很慢? 1 3 5 6 8 3 2 7 ] 我们算出了很多的冗余的东西-------所有排名 2 3 3 5 6 7 8 ]
现在问题到3维,(x,y,z) 貌似有点麻烦了。 我们尝试按照上面的思路。对于第一个关键字 进行排序。依旧可以写出dp方程。 dp[i]=max(dp[j]) +M[i] (y[j]<y[i]&&z[j]<z[i]) 与刚才不同的是,现在的限制还剩2个,求的 是满足y[j]<y[i]&&z[j]<z[i]里面最大的dp[j]。一维 的线段树无法满足要求了。 二维?空间吃不消。 线段树套平衡树。嗯,貌似时间是够了,但是 代码有点麻烦。
不难算出这个算法的复杂度O((N+Q)log^2N) 现在问题变成了2维? 很好解决,我们只用到了树状数组,直接拓展 成2维就行了 For x Sx to N step x&-x For y Sy to N step y&-y D维? 直接拓展就行了。 是不是很简单? 的确,这个方法简单高效。
这个问题怎么算? 调用上面的算法? O(N^2Q) TLE 数据结构思路,二维线段树套平衡树? 代码复杂,复杂度过高。 上面的算法没有考虑到对于多组询问的情况进 行加速,对于单个个询问直接计算第K大数。 我们尝试对暴力算法进行一些改进。 依旧先考虑1维。
我们通过一次划分很快的确定了一次询问的范 围,其基本思路是将数列分成的几乎相等的2部分, 左边小于等于右边,接着快速确定询问的所属答案 范围。 本质是通过划分后的快速判断。 我们发现确定一个询问所在答案范围的代价很 小。 因此我们依旧采取这样的思路,对于所有数按 照大小进行划分然后快速确定所有的询问其所在的 答案区间。
的数 [ 1
其实我们只需要的是排名为K的数。
怎么加快这个算法?
我们不难想到一个基于快排的分治算法。 在一次的划分过程中。 [
[
1
3
5
6
8
3
2
7 ]ຫໍສະໝຸດ Baidu
1 3 5 3 2 6 8 7 ] 考虑到如果我们需要的是第4小数。由于6左边 的数都小于等于右边的,而左边集合的元素多于6 个。因此我们查找的范围必然是 [ 1 3 5 3 2 ]
将范围内的点按照第二维大小排序。 我们定义Solve2(L,R)处理的在第一维划分完的 情况下。满足第一维限制,第二维限制在(L,R)内的 dp值。 依旧取中点值Mid,将带入的状态按照其第二维 的大小分开。用小于第二维小于Mid的dp值向第二维 大于Mid的dp状态转移。接着划分成Solve2(L,Mid) 和Solve2(Mid+1,R)。 这样一来问题变成了2维,简单很多,我们可以 直接采用排序+树状数组求dp值就行了。 算法复杂度为O(Nlog^3N)
dp[L..Mid]里面的值向dp[Mid+1..R]转移的时 候没有第一个天数的限制。是可以直接转移的。 或者说问题退化成了1个3维限制问题,不过一 些是只转移出去一些只是要转移进来。 3维的问题怎么解决? 前面提到过,树套树解决。不过我会说这个 不是一个好办法,本人不是非常喜欢平衡树的常数 以及代码复杂度。 既然我们都已经对第一维分治了我们为什么不 能分治第二维。
往往在竞赛中的优势就是常数小,代码简洁。 这不仅仅是由于大问题和原问题类似,还有是 由于进行分治之后会多出很多很好的性质方便我们 解题。 本文着重是讲述了关于他在解决一类通过分治 限制来解决问题的方法。 往往以前在解决这类问题的时候笔者都会采用 一些暴力的数据结构,下面通过对比你会发现原来 还有很简洁的做法。 我们来看看下面一道题。
现在问题回来成为4维限制的问题。 顺理成章的。我们想到将其按照第一维排序, 现在的dp方程成为了: dp[i]=max(dp[j]) +M[i] (x[j]<x[i]&&y[j]<y[i]&&z[j]<z[i]) 排完序后的限制还剩下3个。 我们依旧采用数据结构维护? 树套树套树? 这不是个好办法吧。。。。可行性比较低。 你会想说3维树状数组套hash? 我会说这个想法不错,但是hash的常数太大。
对于每个询问的范围不同。我们需要查询的是 每个区间内的红点个数,满足加和性质,因此树状 数组可以很好支持这种询问。 定义Solve(L,R),处理这样的一些询问,答案 在(L,R)之间,我们的目标就是Solve(1,N) 。 取Mid=(L+R)/2,把大小[L,Mid]内的点插入树 状数组中,然后把这些询问带出来算一下所在区间 内的点的个数是否满足K。就可以确定是在[L,Mid] 还是[Mid+1,R]。递归处理Solve(L,Mid)以及Solve (Mid+1,R)。
这里我们通过不断划分限制从而实现对原问题 的降维简化了问题,得到一个十分简单而又高效的 算法。 正如刚开始说的那样。我们通过分治算法的不 断分治使得原问题减少了限制或者多了一些性质。 从而方便我们对原问题的解决。
分治算法是很多高级算法的基础,他的思想痕迹 在很多方面都有体现。 本文讲解了一些分治算法在通过一些划分在对问 题的简化或者是转化从而实现问题的解决。 本文中的分治算法相对于经典算法有几个优势: 1.代码简洁方便调试 2.思维复杂度低,节约时间。 3.常数小。 这三点在现在的信息学竞赛中显得尤为重要,因此 他可以在一些题目中代替繁琐的数据结构成为解决问 题的利器。
据说fish国度有着一种很神奇的鱼每条鱼有着 身高Hi、长度Leni和体重Wi以及自己的能量Mi, 大鱼会吃掉小鱼来增加自己的能量(能量相加)。每 一天都会来一条这样的鱼,它总是最多会选择一条 小于自己的鱼然后吃掉它增加自己的能量并进入睡 眠状态。现在YX想到个问题,N天后最后拥有能量 最大的鱼最多能有多少能量。 (定义一条鱼大于另外一条鱼的条件为身高, 长度及体重都大于对方的。)
大丰市高级中学
余翔
何为分治? 具体说就是分而治之,通过不断的分将大问题 转化为小问题,借助小问题的快速解决来高效的解 决原问题。 一般分治有如下的代码过程: Solve( A question S ) Divide S into some questions Si For each Si Solve( Si ) Return Merge_solve(Si) 简单来讲就是 划分—求解小问题—合并
Thank you for listening
Questions are welcome
相关文档
最新文档