您的位置:首页 > 其它

【QBXT】学习笔记——Day8分治

2018-01-22 22:03 253 查看
今天一早上就睡晚了呢0.0,七点半才起床

今天讲的可是分治啊!

分治的原理就是将一个大问题分成两个子问题,子问题再继续分下去。

将简单的子问题处理完以后和并起来得到大问题的答案。

divide−conquer−reduce

Concuerreny问题

给出n个数,计算它们的和,要求速度快。

如果普通的算法就是一个个加,递归层数4层。

并行算法:解决两个或多个子问题时,同时扔到两个或更多CPU上运行。

运行的时间只是解决一个子问题数量。显然运行速度与递归层数有关。

接下来给出一个数组,求前缀和。看这篇博文0.0

接下来要求设计一个并行的排序算法

双调序列:先单调递增,再单调递减的序列(或反过来)

双调序列排序:左右分成两段,同时从左到右枚举,小的放左边,得到两个双调序列。

并且:左边的双调序列元素小于右侧的双调序列所有元素。

迭代这个过程,长度为2的双调序列=有序。

老师讲这个东西,先画了一个倒着的V,然后把V的右边平移,整个序列是一个X

我们用一个扫描线,从左往右比较上下两个元素,将大的元素放在右,小的放左。

如何得到一个双调序列?我们同样分治

首先将第1/2组从小到大排序,3/4组从大到小排,5/6组从小到大…

这样将相邻两组放在一起就是一个双调序列,然后我们再安装上面的方法。

这样一直排下去,就可以得到一个最大的双调序列。

这个复杂度在并行的情况下应该是O(log2n)

这个东西叫做排序网络。

主定理- -



然后我们就要开始解题了:

Maximizing Unimodal Arrays双调序列最大值

显然将这个序列差分一下我们就可以二分了233

但是上面是错的,因为如果有相同元素怎么办呢?可能会GG。

三分法!

其实就是比较a[mid]和a[mid+1],

<则递归右边,>则递归左边,=则两边都递归。

如果全部数都相等就GG了。

Common Algorithms

目标:找到第k大的数。

这个东西和排序有点不一样233,只用找到就行了。

简单的分治算法:选择一个主元,我们递归左边,看左边有多少个数比主元大,设为m

若m<=k,则在左边,否则在右边,往下一层找即可。

那么问题来了——我们如何找到这个主元?

可以随机!但是这个东西是被很好解决了的:

FindMedian算法:

把数组分成n5份,找到每一份的中位数。递归调用中位数算法,找到中位数的中位数。

然后最后用这个中位数作为主元即可。这样分完以后,两个区间最小是原大小的310

根据主定理T(n)=T(n5)+T(7n10)+O(n)=O(n)

这玩意的发明人真是牛啊- -(不想列了)

不过这个东西也不好在这写是吧,那么我们还是直接随机吧。

随机炸到n2的概率是:2(n−1)n!,应该还好吧,这个以后可以推算0.0

Tiling with Triominoes

给定一个n×n(n=2k)的矩阵,使用三格的L形骨牌进行覆盖。

问最优方案里,有多少的位置不能被覆盖到,覆盖方案是多少。

首先假定右上角这个格子不能被覆盖,分开这个矩阵,变成了n2×n2的矩阵

这样我们在中心的位置放一个L的骨牌,显然左上左下和右下,经过归纳后,都可以放完。

而左上角显然是一个子问题。归纳下去,我们可以得到一个方案,使右上角不覆盖。

将这个结论推广,不论我们选中哪一个格子不被覆盖,我们都可以构造一个方案出来。

Integer Multiplication

高精度乘法,给定两个长度为n的整数,求他们的乘积。

我们可以用FFT,当然更好的是用65536进制,因为进位可以用位运算。



解法就是这样,懒得自己码了。

Similar Trick:Strassen Algorithm

讲了矩阵乘法的优化分块??然后就可以降低复杂度,但是没用。

CF888E

给定n个正整数ai和一个模数m。找到一个子集B,最小化:

(∑b∈Bb)modm

n<=35,ai,m<=1e9

看起来很难,其实就是爆搜。Meet in the Middle想法

爆搜前一半,爆搜后一半然后合并。

前一半的mod数弄出来以后排序,然后对于后一半的每个mod数在前面二分找就行了。

CF868F

给一个长度为n的序列ai,现在要求分成k块,

每一块的代价是“值相同但是位置不同数对个数”,求最小总代价。

n<=105,2<=k<=min(n,20),ai<=n

n2∗k的方法很显然了

f(n,k)=min(f(i,k−1)+cost(i+1,k))

显然f(n,k)这个函数关于k是单调的

考虑计算两个值f(i,k)和f(j,k),i′和j′是两个决策点(即最后划分点),

显然决策点的位置也是单调的。

考虑i有两个决策点a和b,且a<b,决策点前的值相等。

如果我们在后面加一个元素,那么扩展的区间的cost,a显然是不小于b的。

这样子我们可以大力分治。

考虑这一类问题的做法:

如果现在分治区间L M R,分治区间L’ M’ R’,那么已知L’和R’,如何得到M’

事实上我们从L’到R’直接扫一次就行了。

BZOJ3263:三元逆序对(权限题)

给定n个三元组(Ai,Bi,Ci),找出所有的i,j,使得三元内严格小于

n<=105,Ai,Bi,Ci<=2∗105

偏序题就是每一维用一个数据结构。

三维就是用排序干掉一维,然后CDQ一维,再树状数组一维。

对于这题,我们按照Ai排序,考虑对长度分治,每次考虑[L,R]区间内的答案。

递归处理两边,考虑所有跨越中间点的数对,满足i在左区间,j在右区间。

我们从小到大枚举Bi,用线段树维护Ci。

即每遇到左边的一个Bi,我们就将Ci这个值放进线段树(维护每个值出现多少次)。

如果遇到右边的一个Bi,我们就求一下这棵线段树在1~Ci的和。

BZOJ3456贸易线路

求点数为n的简单无向图的个数。简单图:无重边,有自环。n<=105

戳这里

递推式是fi=2C2i−∑i−1j=1fj∗Cj−1i−1∗2C2i−j

然后左右两边同除(n−1)!

fi(i−1)!=2C2i(i−1)!−∑i−1j=1fj∗2C2i−j(j−1)!∗(i−j)!

∑ij=1fj(j−1)!∗2C2i−j(i−j)!=2C2i(i−1)!

那么这是一个卷积的形式,我们令:

A=∑ni=1fi(i−1)!xi

B=∑ni=02C2ii!xi

C=∑ni=12C2i(i−1)!xi

则A∗B=C

那么A≡C∗B−1(mod xn+1)

也就是多项式求逆。

ZOJ 3874 Permutation Graph是和上面那题差不多的练习题。

Balkan OI 2007:Mokia

有一个W×W的棋盘,每个格子有一个数,初始为0。

维护两种操作:Add:(x,y)加A,Query(x,y,xx,yy)询问矩阵和

显然可以用二维线段树做。

当然也可以用CDQ分治做。

实际上我们只用考虑前一半操作对后一半操作的影响。

问题转化为给定点集(x,y,A),查询若干个矩阵内的点。

BZOJ2716天使玩偶

维护一个二维平面,支持如下两种操作:

1.插入一个点(x,y)

2.询问一个点(xq,yq)最近的点,曼哈顿距离

|x,y|<=105,q<=105

首先分治,考虑左半边已经加入的点对右半边的影响。

dis(i,q)=|xi−xq|+|yi−yq|

曼哈顿距离常用套路,分四种情况讨论。

先解决dis1(i,q)=(xi−xq)+(yi−yq)

求满足:xi>xq,yi>yq,且xi+yi最小的点。

带权为xi+yi的点集,二维区间最值。

上午讲的东西,其实很大程度上是处理一种”依赖关系“

即分治时如何处理前面对后面的影响。

但是上午讲的东西确实超乎了我的认知233

Day8 1.22NIGHT

今天考试很烦啊,T1T2都是秒的题,然后都挂了。

T1老师讲了一个置换群的问题:

一个置换的n次方就代表这个置换进行n次。然而并没有什么用。

倍增乱搞写挂了??

没有判0。

T2写分治,然后又写挂了???但是本地测是过的(上面是RE)

听说O(qe)可过。然而不关我事啊

如果没有去掉一个物品的限制,就是一个简单背包。

rqy神犇的思路是对整个区间进行分块,然后每个块背包,再合并。

老师的算法是这样的:

考虑已经有一个背包,那么现在要加入一个新的物体。

复杂度是O(背包大小的),这是十分简单的,但删除是很困难的。

考虑分治算法。

假设现在要求12到34这区域的dp值,

其他区域的dp值一定使用到这个区域的dp值。

这样我们每次分到一部分时,我们将所有外部的dp值都传到这个部分。

然后再进行合并。

也就是说,对于每个区块,我们将右边的dp值丢到左边去算,

同样将左边的dp丢到右边去算。

我的思路也是分治,同样是将一部分的dp值丢到另一边然后dp。

但是在写法上有点不同。

用单调队列优化以后复杂度应该是O(nlogn)的

写挂了很可耻可耻可耻。并没有写挂。

rqy的T3的40pt是这样的:

首先点——边——点的最短距离就是作对称点然后连直线求交。

对于有两条边(即点——边——边——点)的情况也是一样的。

然后就这样水,不断按多边形的顺序跑。

为什么呢?因为跑的路线一定是不交的(如果交一定可以替换为更优的)

但是这样做的时候有个问题,因为可能连起来的直线不在线段上。

正解在这里:

最后的答案一定是从O出发,经过若干条边的反射到了一个顶点,

然后再从顶点经过若干条边到另一个顶点,最后再回到原点。

f[i][j]表示i这个点和j这个点经过光路最速原理走过去的值是多少。

这是两个点之间仅通过边反射的最短距离。

然后我们再用floyd求出任意两个点之间的最短路。

预处理另外两个数组,一个是从原点出发,顺时针反射到某个点的距离,

另一个是从原点出发逆时针反射到某个点的距离,这样线性扫一遍就行了。

计算几何和图论的结合,真好玩啊。

然后我顺便找到了原题,是2012ACM-ICPC-WF的H

WC2007疯狂赛车,也是这样一种题目。

然后继续讲课了

NOI2007货币兑换——分治好题233

有两种操作,n天进行货币买卖,第i天可以进行两种操作。

1.花费s,按照市值ai,bi收获两种股票,两种股票的比例是固定的r_i

2.给定一个比例k,按照市值ai,bi把手中k的持有的A和B卖掉。

给定所有参数问底n天后最大持有现金数。

一个很显然的结论是每次都会操作所有的现金/股票

f[i]表示第i天最多有多少钱。

那么我们枚举上一个买入交易日j,第j天花所有钱买入股票,在第i天全部卖掉。

f[i]=maxf[i−1],fa(j)∗a[i]+fb(j)∗b[j]

fb[j]=f[j]a[j]∗r[j]+b[j]

fa[j]=a[j]∗f[j]a[j]∗r[j]+b[j]

对于i,决策j优于k的条件是:

r[j]∗f[j]−r[k]∗f[k]f[j]−f[k]>−b[i]a[i]

但是这个斜率优化的单调性十分的差,我们动态维护这个凸包很难。

平衡树是可以的。但我们考虑更简单的做法(也许吧,我是这么认为的)

其实,我们接下来需要干什么?

1.加点,维护上凸壳

2.用一条固定斜率的线从上往下扫描,回答碰到的第一个点

其中第二个问题等价于在凸包上二分。

考虑CDQ分治,我们先计算出左半边点的dp值,

考虑左半边的dp怎么影响右半边?

——左半边的点可能被右半边的询问线碰到。

操作变成:

给定左半边的点集,构造凸包;

给定左半边的凸包,二分右半边的斜率在左半边的位置。

这题的主要思想是利用CDQ将一些动态的东西转化为静态的。

这样做是O(nlog2n)的

考虑进一步优化。

我们比较容易想到的是二分的优化,将右半边的询问斜率进行排序。

然后我们二分后的斜率选择的点就是单调往右的。

再考虑第二步优化,因为我们已经分治了,不妨将下一层的凸包也传上来。

凸包的合并是可以做到O(n)用两个指针单调扫的。

这样复杂度就被优化到了O(nlogn)

这道题的思想是十分重要的,回去一定要好好写一次。

练习题:WF2011,Machine Works

POI2011:METEOR

有m个天文台排成一个环形,每个天文台属于n个国家中的一个。

有k场流星雨,第i场波及[l[i],r[i]],为每个天文台提供ai的陨石

每个国家有陨石需求量bj。问每个国家在第几场流星雨后达到陨石需求。

这道题在当初讲整体二分的时候做了0.0

线段树可以维护流星雨的信息,但是怎么统计呢?

我们可以用整体二分233,就是对答案进行分治。

每次询问加上[L,M]这段区间的流星,有多少国家满足了。

满足的二分左侧区间,不满足的二分右侧区间。

右侧区间信息怎么维护呢?我们可以用主席树/撤销操作/简单统计。

BZOJ3110 K大数查询

有n个vector:vi排成一排,维护以下操作:

1abc,对于i∈[a,b],vi.push_back(c)

2abc,查询Ui∈[a,b]vi集合的第c大元素

第二个操作就是合并[a,b]这些区间后的第c大。

这也是经典题目啊,数据结构题QvQ,但哦我们还是要整体二分做!

我们对答案“分治”。那么每次要求的就是对于每一个询问 a,b→ans。

扫描所有操作,每次询问是否存在至少C个数,他们<M(二分的M)且在[a,b]区间范围内

查询就是查询一段树是不是大于C

总结一下

分治是一个很有趣的东西,

绝大多部分题,尤其是CDQ分治和整体二分,

将动态的问题变成了一些静态的东西。

最后听说是一道娱乐题:K近邻相交查询

给定n个排序的实数,有若干组询问:

(x,y,k),询问距离x最近的k个点和距离y最近的k个点是否有交集

假定对于每个点没有两个点和它距离相同。

n,k<=105,ai<=109

又是rqy讲的qwq

显然距离每个点前k近的点是一段连续的区间。

二分距离x第k近的点距离是多少,然后我们再二分一次,距离x不超过v的点距离是多少。

这个做法是O(nlog2n)的

二分以每个点为中心往外扩k个,那么显然我们要看看x左延和右延的哪边距离大

balabala

这个做法是O(nlogn)的

然后还可以拓展下,变成二维询问曼哈顿距离的K近邻相交查询

做法是一样的。

但是我们可以考虑旋转45度233

对于每个询问我们就可以转化为旋转45度的矩形有没有交。

今天真的是很不爽啊

做题量太少的后果。

明天要开始学数学了,十分慌张QAQ
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: