2020寒假集训Day2 分治与分块 总结

41 篇文章 1 订阅
27 篇文章 0 订阅

(只讲新学会的)

1、点分治解决合法括号序列路径计数

首先每一个括号序列可以把它缩成一堆)))和一堆(((

记录一下当前点分治中心到子树中任意节点的简化括号序列的剩余左右括号数目(要记录两种一种是从上向下、另一种是从下向上),然后在点分治中心合并答案即可

至于怎么记录从下向上的简化括号序列,可以考虑从序列左边插入括号来维护栈

 

2、点分树

一棵树,n个点,有点权,多次询问,求到点x距离小于等于k的节点的点权和

先考虑点分治的过程,把每次的分治中心按层排列为树形结构

那么点x为分治中心时所管辖的点的合法点权和可以通过nlogn预处理出来(直接用一个数组做前缀和)

然后找到x点在点分树上的父亲,向上跳,查询,减掉来自x子树的贡献(点分治经典去重)

因为点分树的深度是logn的,所以一次查询是logn的

如果可以修改点权?

把每一个点分治中心维护的前缀和数组改为树状数组即可,一次查询需要(logn)^2

 

3、边分树

(1)、三度化

就是加入0权边和虚点,把菊花图优化一下,这样边分治就不会被菊花图卡了

(2)、边分树

其实解决问题的方法和边分树差不多,只不过它有一个优点就是,它是二叉树,方便合并

但是也有缺点,如果问题无法三度化(或三度化之后会影响准确性),就不能用边分治

 

 

4、[ZJOI2007]捉迷藏

计算最远黑点点对的距离,带修改颜色,有边权

题解:建出边分树

对每个边分治中心开一个multiset,维护该边分树子树节点到当前边距离的集合

然后两边找最大的合并即可(就像线段树)

如果要修改颜色,就需要改logn个multiset的值才能再一次维护处全局的答案,所以是(logn)^2

也有不用multiset的做法

就是每一个边分治中心存一下它管辖范围的直径端点,然后每次向上合并的时候都需要用6次LCA(如果把之前的直径长度存下来就是4次)

 

5、[ZJOI2015] 幻想乡战略游戏(占坑,后面还有很多内容)

 

6、一道CF的题

一棵树,点边均带权,找一个点x使\sum_{i!=x}a_i*dis(i,x)^{1.5}最小(a为点权)

做法:建出点分树

然后从整棵树的分治中心向下走,每次找答案最小的儿子走(有点贪心,因为x^1.5是凸函数,所以就可以通过比较导数来确定最优解的位置,有点爬山的思想)

 

7、环形邮局问题

法一:随机破环为链

法二:由于四边形不等式的本质就是交错更优,所以我们可以随便选一个点作为起点

用wqs二分求出它的决策点集合,然后找到最近的两个决策点,在他们之间来进行枚举

时间复杂度O(n^2/k*logn*logn)或O(n^2logn)

法三:利用最优路径和当前路径不交叉的性质,分治套分治,O(n*logn*logn)

 

8、分块,块内维护所有值的有序序列解决区间小于等于k的数的个数

区间查询:两边暴力,中间在每个块内二分

区间加修改:中间的打标记,两边下放标记,块中把修改的数与没修改的数用归并排序重构

总复杂度O(m*sqrt(nlogn))

块大小sqrt(nlogn)

(注意这里的loglogn是被忽略了的)

 

9、分块解决区间第k大,区间加(Ynoi2017舌尖上的由乃)

区间查询:对每个块进行二分,边缘的两个块归并起来二分

区间修改:同8

块大小sqrt(n)*logn

时间复杂度O(m*sqrt(n)*logn)

 

 

10、根号平衡(为莫队做铺垫)

值域分块(注意这里的第k小时全局的第k小)

先把所有的值离散化一下

每一个块维护一个已经存在点数,显然,这样可以做到O(1)维护

然后查询就直接从1号块的点数一次累加,当超过k时,就说明答案在当前块中,在扫一下当前块内部就可以了

相当于写了一个O(1)insert,O(sqrt(n))query的set

 

块状链表(思路差不多)

还是对值域分块

插入的时候暴力找到插入的位置,然后块内直接插入,这时这个块可能会挤出来一个元素(我们要把每个块大小为sqrt(n),除尾端块),于是我们就把这个元素放到下一个块中,然后可能就会挤出来一个元素……挤出来的元素只会是块尾,最多可能挤出来sqrt(n)次,所以复杂度是sqrt(n)的

怎么查询?

直接数学方法定位即可(因为前面的每个块的大小都是sqrt(n)了)

 

 

11、一道codechef的题

题解:

思路非常巧妙

对函数编号分块,每个块统计一下它当前的函数值总和

这样查询应该都会了

怎么修改?

每个块维护一个差分数组,把块内函数的左端点++,(右端点+1)--,单点修改的时候就需要看当前点对每个块答案的贡献

这个贡献就是它在一个块中,分别被多少个函数覆盖,直接查当前位置x的前缀和就可以了

总时间复杂度:O(m*sqrt(n))

 

 

12、莫队如何卡常数

 

 

对了,莫队的复杂度是O(n*sqrt(m))的,不是O(m*sqrt(n))

 

 

13、[Ahoi2013]作业

一看就可以直接用莫队+树状数组

但是会TLE

因为莫队等价于n*sqrt(m)次修改操作与m次查询操作

如果能将修改操作的时间复杂度降下来就好了

联想到之前的值域分块,稍加思索,就有了一个O(1)insert,O(sqrt(n))query的set了

复杂度就降为了

O(m*sqrt(n)+n*sqrt(m))

感觉还是会TLE啊。。。

 

 

14、 [Ynoi2016]这是我自己的发明

(先占一个坑,主要是不会换根操作。。。)

 

 

15、[Ynoi2015]此时此刻的光辉

n<=10^5    mod=19260817   。。。

 

题解:

约数个数是可以通过每个质因子的个数来计算的

所以我们先把所有的数分解质因数

然后把所有的质因数离散化

就可以莫队啦

然而这样会TLE

因为一次修改可能会带来logn次操作

怎么办呢?

我们可以按质数大小来分类讨论

我们把1~1000的168个质数预处理出它对答案贡献的前缀和

然后我们加的较大的质数就不会超过三次

这样修改的复杂度就降为O(1)左右了

查询的复杂度就是O(168)约等于O(sqrt(n))

所以总复杂度为O(n*sqrt(m)+m*sqrt(n))

 

 

 

 

(差不多了,其他的都没怎么听懂。。。)

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值