顾昱洲+浅谈一类分治算法
未处理的位置
神一般的 数据结构
例子
• • • • • 最长上升子序列 (树状数组) HNOI 2008 玩具装箱 toy (单调队列) CF 115 E Linear Kingdom Races (线段树) NOI 2007 货币兑换 cash (平衡树维护凸包) ACM ICPC WF 2011 F Machine Works (平衡树 维护凸包)
Pseudo-Animation
已处理的位置
未处理的位置
神一般的 数据结构
Pseudo-Animation
已处理的位置
未处理的位置 查询,求出该 位置的值
神一般的 数据结构
Pseudo-Animation
已处理的位置
未处理的位置
神一般的 数据结构
更新数据结构
Pseudo-Animation
已处理的位置
复杂度分析:时间复杂度
• • • • 点定位查询 O(log n) 线段树查询结点个数:O(log n) 每个结点查询的次数:O(log n) 查询总复杂度 O(n log^3 n)
• 总复杂度:O(n log^3 n)
复杂度分析:空间复杂度
• 每次只需要存储一棵线段树 • 最大的线段树 |A|=O(n) • 每个区间存储的数据结构的空间为O(区间 长度) • 因此总空间复杂度为O(n log n)
劣势
• 必须采用在线数据结构 • -> 存在性、代码量、复杂度 • 存在性:你会做吗? • 代码量:你写得出吗? • 复杂度:写出来你A的掉吗?
分治算法
• 当前处理区间[L, R),中点为M • 递归处理[L, M) • 将[L, M)的结果建成一个数据结构,并用其 更新[M, R)的结果 • 递归处理[M, R)
浅谈一类分治算法
南京师范大学附属中学 顾昱洲
从1D1D动态规划说起
• 一维状态,一维转移 • 形式:f(i)=max(w(j, i)) for 0≤j<i • 若w函数单次计算O(1),则暴力复杂度O(n2)
一类1D1D动态规划的优化
• 假设我们能够维护一个数据结构,在低于 线性的时间复杂度内在线支持: • (1) 插入 (2) 查询 • 那么可以在低于平方的时间复杂度解决原 问题
• 只添加结点的二项堆
• 从左向右每个点分别查询并插入、实时删 除无用结点的线段树 • 分治:A集合中点更新B集合中点,A集合中 点建立数据结构后B集合中点的值可以在线 查询 • 三者是等价的
Reduction (无用边)
• 将需要修改的边边权标记为正无穷,做MST • 原图中边权非正无穷且不在MST内的边,在 还原边权后必然也不在MST内 • 删除这些边,减少边数 • 还原边权
Pseudo-Animation
1
1 inf 4
3
3
2
红边为待修改边
Pseudo-Animation
1
1
3
3
2
最小生成树
Pseudo-Animation
1
1 4
3
3
2
该边无意义, 被删除
Pseudo-Animation
1
1
3
3
2
Contraction (必须边)
• 将需要修改的边边权标记为负无穷,做MST • MST中非负无穷边,还原边权后必然也在 MST内 • 将这些边连接的点集合并,缩小点数 • 还原边权
必须离线?
• 注意到我们这里的转移方式并不要求将B中 的所有点一起转移 • 可以改变转移顺序使得转移成为在线 (即, 可以在末尾增加一个点) • 使用空间会增加,但是空间复杂度不变 • 详见讲义
不仅是动态规划
• “动态”问题 • n个状态(操作),每个状态(操作)对后面的状 态产生影响
• 只能动态做?
分治算法
• 转化原问题 • 已处理点集A,待处理点集B • 对于B中每个点j,求A中在圆j内的点最大F 值
再次转化
• 将A中点按照F值排序 • 二分F值最大的点,判断F值不大于它的点中 到j的最短距离是否小于R[j]
线段树
• 将A中点按F值排序后建立线段树 • 每个区间内存储该区间内所有点的Voronoi 图以及点定位数据结构
Actual-Animation
未处理的位置
递归处理
Pseudo-Animation
已处理的位置
未处理的位置
神一般的 数据结构
Pseudo-Animation
已处理的位置
未处理的位置
神一般的 数据结构
Actual-Animation
已处理的位置
未处理的位置
递归处理
例题 (陈立杰)
• 给定平面上n个点的坐标,每个点有两个权 值R[i]和C[i] • 点i到点j有边当且仅当i<j且点i到点j的欧几里 得距离 < R[j] • (即i<j且在点i在点j的圆内) • 求一条路径,使C[i]和最大
预备知识
• 给定大小为n的点集A,我们能够在O(n log n) 的时间复杂度内建立一个数据结构,支持 在O(log n)的时间复杂度内查询给定的一个 点B到点集A中点的最短距离
• 例:Voronoi图+点定位数据结构
思路
• 简单的平方算法:直接DP • F[i]为以i为终点的路径的最大C值和 • 在线数据结构维护:不会做 (?)
时间复杂度
• 假设当前需要处理的区间长度为k • simplify需要 O(k log k + k α(k)) • 实际上,O(k log k)的排序部分可以通过归并 排序变成O(k) • 总时间复杂度? • 根据主定理只能知道 T(n)=Ω(n log n) 以及 T(n)=o(n log^(1+eps) n)
优势与劣势
• 可以采用离线数据结构 • -> 存在性、代码量、复杂度 • 题目必须允许离线 (?)
Thanks
例题一:在线维护?
• 我确实不会做 = = • 不过这里有一些思路
(伪)动态Voronoi图
• 支持:加点、询问 (均在线)
• 还记得例题一的做法实际上是在线的么?
二项堆、线段树与分治
• R-C-R过程: • (n, m) => (n, n+k-1) => (k+1, n+k-1) => (k+1, 2k)
流程
• 当前处理区间[L, R),中点M • 若L=R-1,则此时点数和边数均不超过2,直 接实行修改,记录答案并退出 • 删边、缩点 • 递归处理[L, M) • 递归处理[M, R)
分治算法
• 分治算法的根本是减少数据量 • 需要修改的边数是可以接受的 • 瓶颈在于图的点数和边数
思路
• 有一个带边权图G,有k条边在之后会被修 改 (并询问MST) • 在这k个MST中,有一些边是永远不会在 MST中的;而另一些边是必须在MST中的
• 我们可以试图求出这些边,以缩小图的规 模
其他题目
• BOI 2007 Mokia • POI 2011 Meteors • 2012年集训队互测 梁盾 矩阵乘法
总结
• 动态问题:n个状态(操作),每个状态(操作) 对之后的状态施加影响
• 分治算法:通过分治,处理看似难以处理 的影响 • 1D1D动态规划的分治算法:将连续一段影 响同时处理 • 动态MST的分治算法:减小数据量,减少实 施影响的花费
Pseudo-Animation
1
1 -inf 4
3
3
2
红边为待修改边
Pseudo-Animation
1
1 -inf
3
2
最小生成树
Pseudo-Animation
1
1 4
3
3
2
四条蓝边为必须边
Pseudo-Animation
1 3 2
1 4 3 缩点
Pseudo-Animation
3
4
缩点Biblioteka 动态最小生成树• 维护一个图,每次修改一条边的权值(可以 增加或减少),并返回最小生成树的边权和 • 所有修改预先给出,即可以接受离线算法 • (本题支持加边删边,只要允许正无穷边存 在即可)
思路
• 暴力:单次修改O(n)
• 在线算法:非常复杂,目前已知的最优算 法,单次修改O(log^4 n)
• 二分时每次取的是线段树的区间端点,因 此对于B中每个点,事实上只查询了线段树 的O(log |A|)个区间。
复杂度分析:时间复杂度
• Voronoi图+点定位数据结构:O(k log n) 其中 k为Voronoi图点数 • 线段树:O(|A| log^2 n) • Sum |A| = n log n • 建立总复杂度 O(n log^3 n)
减少点数和边数
• Reduction-Contraction-Reduction
• 假设当前区间内修改的边数为k • 进行R-C-R后,图中最多只剩下k+1个点和2k 条边 • 可以接受
简单的证明
• 初始:n个点m条边 k条待修改边 • Reduction后:最多剩余n+k-1条边 • Contraction后:最多剩余k+1个点
NOIP基础算法讲解2
while(i<=mid)do begin temp[p]:=a[i];inc(p);inc(i);end while(j<=right)do begin temp[p]:=a[j];inc(p);inc(i);end for i:=left to right do a[i]:=temp[i]; end;
数据范围:n≤10^6。所有数之和不超过10^9。
例题8:快速幂
【问题】计算an mod k的值 ,其中n<=109。
方法1:朴素算法。每次乘以a,时间复杂度O(n)。 function power(a,n:longint):longint; var x:longint; begin x:=1; for i:=1 to n do x:=x*a; power:=x; end;
时间效率不尽如人意….. 问题出现在哪里呢??
方法2:分治策略
采用分治求解: ➢划分问题:把序列分成元素个数尽量相等的两半; ➢递归求解:统计i和j均在左边或者均在右边的逆序对个数; ➢合并问题:统计i在左边,但j在右边的逆序对个数。
记数列a[st]~a[ed]的逆序对数目为d(st,ed); mid=(st+ed)/2,则有:
三、分治的三步骤
①划分问题:将要解决的问题分解成若干个规模较 小的同类子问题;
②递归求解:当子问题划分得足够小时,求解出子 问题的解。
③合并问题:将子问题的解逐层合并成原问题的解。
四、分治的框架结构
procedure Divide() begin
分治法的个人总结
分治法是一种算法设计策略,它将问题划分为较小的子问题,然后通过解决子问题来解决原始问题。
个人总结如下:
分解问题:分治法首先将原始问题分解为规模较小的子问题。
这可以通过递归地将问题划分为更小的部分来实现。
分解问题的关键是确保每个子问题都是原始问题的规模的一个子集。
解决子问题:每个子问题都可以通过相同的算法来解决。
递归地应用相同的算法,直到达到基本情况,也就是子问题可以直接解决的规模。
合并解决方案:一旦解决了子问题,就将它们的解合并起来,形成原始问题的解。
这通常涉及对子问题的解进行组合,以获得原始问题的最终解。
适用性:分治法适用于那些可以自然地分解为子问题的问题。
它在解决许多常见问题时非常有效,如排序、搜索、计算最大值和最小值、归并等。
时间复杂度:分治法通常在每个子问题上执行相同的操作,并且子问题的数量通常是对数级别的。
因此,分治算法的时间复杂度通常可以表示为递归深度的多项式。
常见的时间复杂度包括O(nlogn)和O(n^2)。
并行化:由于分治法的子问题通常是相互独立的,因此它很适合并行化处理。
可以同时处理多个子问题,然后将它们的解合并起来。
这使得分治法在并行计算中具有较好的可扩展性。
总的来说,分治法是一种强大的算法设计策略,它通过将问题分解为子问题并递归地解决它们,然后将子问题的解合并起来,从而解决了许多复杂的问题。
它在算法设计和并行计算中都具有广泛的应用。
常见算法的解题思路(论文集)
穷举算法解题的一般思路穷举算法是程序设计中使用得最为普遍、大家必须熟 练掌握和正确运用的一种算法。
它利用计算机运算速度快、 精确度高的特点,对要解决问题的所有可能情况,一个不漏 地进行检查,从中找出符合要求的答案。
用穷举算法解决问题, 通常可以从两个方面进行分析:一、问题所涉及的情况:问题所涉及的情况有哪些, 情况的种数可不可以确定。
把它描述出来。
二、答案需要满足的条件:分析出来的这些情况,需 要满足什么条件, 才成为问题的答案。
把这些条件描述出来。
只要把这两个方面分析好了,问题自然会迎刃而解。
例 1:36块砖,36人搬。
男搬4,女搬3,两个小儿 抬一砖。
要求一次全搬完。
问需男、女、小儿各若干?分析:题目要我们找出符合条件的男生、女生和小孩 的人数。
答案显然是一组数据。
首先分析一下问题所涉及的 情况。
对于男生来说,至少要有一人;每个男生可以搬4块砖, 那么36块砖最多9个男生足够, 共有9种不同取值。
同样,女生有12种不同取值。
两个小孩抬一块砖,至少要 有两个小孩,最多36个,并且小孩的人数必须是个偶数, 所以小孩的人数可以取18种不同的值。
最坏情况下, 男生、 女生和小孩的人数可以是9×12×18=1944种不同组合。
知道了问题所涉及的情况有1944种,是个确定的数。
接下来就要把它描述出来。
描述的时候用什么计算机程序设 计语言都可以,我这里就以QBASIC语言为例: 假设男生人 数为x,女生人数为y,小孩人数为z。
可以构建这样一个 三重循环for x=1 to 9for y=1 to 12for z=2 to 36 step 2循环体next znext ynext x理论上这个循环的循环体将执行1944次,我们可以 用它来对问题所涉及的1944种不同情况逐个进行检查。
分析完问题所涉及的情况后,第二步就要看看答案需 要满足什么条件。
仔细阅读一下题目,我们就会发现,答案 x、y、z的值必须要同时满足两个条件:①总的工作量是 36块砖,即:4x+3y+z/2=36;②需要的总人数是36人, 即:x+y+z=36。
如何应用分治算法求解问题
如何应用分治算法求解问题分治算法,英文名为Divide and Conquer Algorithm,是一种高效的算法设计策略,在计算机科学中有着广泛的应用。
该算法将一个大问题分解成多个小问题,各自独立地解决,再将结果合并起来得到最终结果。
在本文中,我们将阐述如何应用分治算法求解问题,并通过几个实例来具体说明该算法的应用。
一、分治算法的原理分治算法的核心思想是将一个大问题分解成若干个小问题来解决,然后将这些小问题的解组合起来生成大问题的解。
其具体步骤如下:1. 分解:将原问题划分成若干个规模较小的子问题。
2. 解决:递归地解决每个子问题。
如果子问题足够小,则直接求解。
3. 合并:将所有子问题的解合并成原问题的解。
分治算法的主要优点在于它可以有效地缩小问题规模,从而缩短整个算法的执行时间。
另外,该算法天然适用于并行计算,因为每个子问题都是独立求解的。
二、分治算法的应用分治算法在各种领域都有广泛应用,包括数学、自然科学、计算机科学等。
以计算机科学领域为例,分治算法常常用于解决以下类型的问题:1. 排序问题2. 查找问题3. 字符串匹配问题4. 最大子序列和问题5. 矩阵乘法问题6. 图形问题下面我们将一一讲解这些问题的分治算法实现。
1. 排序问题排序问题是在一组数据中将其按指定规律进行排列的问题。
在计算机科学中,排序算法是十分重要的一类算法。
其中,分治算法由于其高效性和可并行性被广泛应用。
常用的分治排序算法包括归并排序和快速排序。
归并排序的基本思想是将待排序元素以中心点为界分成两个序列,对每个序列进行排序,然后将两个序列合并成一个有序序列;而快速排序则利用了分割的思想,通过每次选取一个元素作为“轴点”,将数组分成小于轴点和大于轴点的两部分,对这两部分分别进行快速排序。
2. 查找问题查找问题是在一组数据中寻找某个元素的问题。
分治算法在查找问题中的应用主要体现在二分查找中。
在二分查找中,我们首先将已排序的数组分成两半,在其中一半中查找目标值。
图解算法与算法类问题求解
General 一般过程
算法类问题
Course 课程
TSP问题数学模型
求解TSP问题的算 法策略设计—贪心
TSP问题贪心算法 数据结构设计
TSP问题贪心算法 过程设计
TSP贪心算法程序 (C语言)
数学建模
问
题
算法策略设计
求
解
的
数据结构设计
过
+
程
算法过程(控
及
制结构)设计
思
维
方 程序设计语言及
数学建模与算法策略设计---算法思想 (3)算法思想或者算法策略对问题求解有什么影响?
uTSP问题的难解性:随着城市数量的上升,TSP问题的“遍历”方法计算量剧增,
计算资源将难以承受。
u2001年解决了德国15112个城市的TSP问题,使用了美国Rice大学和普林斯顿大学之间 互连的、速度为500MHz 的Compaq EV6 Alpha 处理器组成的110台计算机,所有计 算机花费的时间之和为22.6年。
TSP问题
算法类问题
TSP问题数学模型
求解TSP问题的算 法策略设计—贪心
TSP问题贪心算法 数据结构设计
TSP问题贪心算法 过程设计
TSP贪心算法程序 (C语言)
u算法是一个有穷规则的集合,它用规则规定了解决某一特定 类型问题的运算序列,或者规定了任务执行或问题求解的一系 列步骤。
如音乐乐谱、太极拳谱等都可看作广义的算法
算法与算法类问题求解 (4)你知道一些典型的算法类问题吗?
算法类问题:由一个算法可以解决的问题,寻找一个(唯一的)方法(算法)
以解决同一类型的无穷多个单个问题系列的问题。
求一旅行商从某城市出发必须经过每一个城市且只能在每个城市逗留一次,
分支定界算法优化一维下料问题
1 一维优化下料问题的具体模型分析
原材 料 长 度 为 L , 数 量 充 足 。需 要 切 割 成
n ( n ≥0 )种不同规格的零件 , 根据既省材料又容易
操作的原则 ,人们已经设计好了 n 种不同的下料方 式 。设第 j种下料方式中可下得第 i种零件 aij 个 , 又已知第 i种零件得需要量为 bi 个 , xj 表示第 B j 种 下料方式所消耗得零件数目 , cj 表示第 B j 种下料方
x = 20 51 0 9 0 24 0 1。
3 实例
设某车间有一批长度为 180 cm 的钢管 ,为制造 零件的需要将其裁成 3 种不同长度的零件 , 分别为
70, 52, 35 cm。这三种零件的需要量分别为 100, 150, 100 根 。问 如 何 下 料 才 使 得 原 材 料 的 消 耗
m in f =
n
∑c x
j j =1
j
if nargin < 10, op tions = op tim set( { } ) ; op tions . D isp lay = ’ off’ ; op tions . LargeScale = ’ off’ ; end
∑a
j =1
ij
xj = bi
最少 ? 分析 :对于一维下料问题都可以用组合最优化的 方法给出合理的下料方式 。设 x1 , x2 , x3 分别表示 在已知钢管上下 3 种不同长度的零件数 ,则 70 x1 +
52 x2 + 35 x3 ≤ 180 ( xi ∈ Z , i = 1, 2, 3 ) 。其中 x1 ≤ 2 ,表 1给出下料方案 。
xj > 0 xj < xj ∈ Z
分治算法初探_方泓杰
Galaxies (福州第三中学)
分治算法初探
June, 2017 13 / 29
树
求带边权的一棵树中长度不超过K的路径的条数。 1 ≤ n ≤ 5 × 104, 1 ≤ wi, K ≤ 2 × 105 考虑对于每个经过重心的路径计算答案。 把重心的所有子树的小于等于K的路径全部放入一个数组中,排序 后two-pointers扫描数组即可。 扣掉路径属于同一个子树(在枚举子树的时候顺便处理即可,方法 和上面一模一样) 复杂度O(nlog2n)
Galaxies (福州第三中学)
分治算法初探
June, 2017 5 / 29
不无聊的序列
给你一个n个数的序列a1, a2, ..., an。定义一个序列是“不无聊的”, 当且仅当对于其的每一个子段,都存在一个数在这段内只出现 了1次。判断一个数列是不是“不无聊的”。多组数据。
1 ≤ T ≤ 10, 1 ≤ n ≤ 2 × 105
这些问题自行解决 正常的生理需求 电脑没电了 人没电了
Galaxies (福州第三中学)
分治算法初探
June, 2017 3 / 29
第一部分:基础分治
bzoj4059 [Cerc2012]Non-boring sequences bzoj4025 二分图 bzoj3237 [AHOI2013]连通图 这一部分的内容应该比较基础,是为后面理解分治做准备。请大家 保持好连接不要断线。
分治算法初探
Galaxies
福州第三中学
2017年6月
Galaxies (福州第三中学)
分治算法初探
June, 2017 1 / 29
关于我
Galaxies(尕拉克西斯) Tony Fang mailto:Galaxies@ /galaxies
顾昱洲-WC营员交流
i =3
• 如何求F(n, k)?
SGU 481 cont’d
• 算两次 • 考虑每个森林,所有边的排列数的和S •= 显然 S F (n, k )( n − k )!
SPOJ PT07D cont’d
• 当然,n为偶数的时候会有双质心。容斥掉 就好了。 • 求b在求出a之后是线性的。 • 总时间复杂度O(n2)
SPOJ PT07D cont’d
• Some Notes
– 如果你看不懂母函数,建议去看《具体数学》 (别看中文版)。 – 之前由于篇幅所限没法写推导过程,建议大家 自己去推一下,还是很有意思的。 – 如果实在推不出来,去看华东师大一附中赵爽 写的《树的计数》。
2 Cn
2
+2
SPOJ KPGRAPHS
• • • • • • 有标号连通图 有标号欧拉图 有标号二分图 要求n=1~1000的所有答案 模109+7 代码长度限制7000B
SPOJ KPGRAPHS cont’d
• 已知n个点的满足P的图的个数S(P, n) • 求连通的n个点的满足P的图的个数F(P, n) • 令G(P, n) = S(P, n) - F(P, n)
经典题 cont’d
• • • • 深度为i的二叉树至少有一棵子树深度为i-1 可以写出DP方程(好长的,一行写不下) 维护F和G的部分和 O(n)
解决图计数问题的一般思路
• • • • 唯一性 算两次 一定的数学基础
• 习题:证明n个点的无标号毛毛虫的个数为
【分治算法】木材加工,解读
【分治算法】木材加工,解读
【实用版】
目录
1.分治算法简介
2.木材加工问题的提出
3.分治算法在木材加工问题中的应用
4.结论
正文
【分治算法】
分治算法是一种将复杂问题分解为多个简单问题来求解的算法思想。
这种算法通过将大问题拆分成多个小问题,然后逐个解决这些小问题,最后将这些小问题的解合并,从而得到原大问题的解。
分治算法广泛应用于各种领域的问题中,例如木材加工问题。
【木材加工问题的提出】
在木材加工业中,有一个经典问题:如何将一根圆木加工成若干段长度相等的木条,同时要求加工次数最少?这个问题可以通过分治算法来解决。
【分治算法在木材加工问题中的应用】
假设圆木的长度为 L,我们需要将其加工成 n 段长度相等的木条。
我们可以将这个问题分解为两个子问题:将圆木加工成 n/2 段长度相等的木条,以及将圆木加工成 n/2+1 段长度相等的木条。
然后,我们再将这两个子问题继续分解,直到子问题的规模足够小,可以用简单的方法求解。
当子问题的规模足够小时,我们可以直接计算出每段木条的长度。
然后,通过将这些长度依次排列,我们可以得到原问题的解。
对于较大的子
问题,我们可以通过递归的方式调用分治算法来求解。
最后,将各个子问题的解合并,即可得到原问题的解。
【结论】
分治算法在木材加工问题中的应用,展示了分治算法在解决实际问题中的强大功能。
分治法应用
分治法应用
分治法是一种解决问题的策略,它将一个问题分解为更小的子问题,然后分别解决这些子问题,最后将子问题的解合并以得到原问题的解。
在计算机科学和算法设计中,分治法是一种非常常见且有效的算法设计方法。
例如,在快速排序算法中,分治法被用来将一个大的数组分割成两个更小的子数组,然后递归地对这两个子数组进行排序。
这个过程一直持续到我们得到一个只有一个元素的数组,然后就可以通过比较这个元素与其相邻元素的大小来得到最终的排序结果。
在计算机图形学中,分治法也被用来解决各种问题,例如在渲染复杂的3D模型时,可以将模型分解为多个小的三角形,然后分别渲染这些三角形,最后将渲染结果合并以得到最终的图像。
此外,在数据库系统中,分治法也被用来处理大规模的数据查询。
例如,可以将一个大的数据库分解为多个小的数据库,然后分别在这些小的数据库中查找数据,最后将查找结果合并以得到最终的结果。
总的来说,分治法是一种非常有效的问题解决策略,可以用来解决各种不同领域的问题。
