今天模拟2013南京赛,两个半小时做完5题开始梦游。
每次都出不了难题有木有!都是水题的场手速又拼不过有木有!
hdu4812 D Tree,南京的k题。
每个点有一个权值,问是否存在一条路径,路径所有点的权值乘积模1e6+3等于k。
这个题,大家基本都是用点分治过的,复杂度O(nlogn)。
这里介绍一个有趣的解法,也是一个我感觉很有用的思想:启发式合并。
先说说启发式合并。
启发式合并就是对于两个相同的数据结构,将点数小的数据结构的点一个个暴力插入点大的数据结构中。
如此就完成了这两个数据结构的合并。
再来说说这玩意神奇之处。
以平衡树为例,一开始有n个点,每个点有包含本身的点的平衡树。
然后将任意两点的平衡树合并,最后合并成一棵树。
如果每次都遵循小的插到大的这样的合并方式,可以证明,插入的次数不会超过O(nlogn)次。
这里简单证明一下:对于每个点,如果它从小的树拔出来插到了大的树上,那么它所在的树的大小至少会增加一倍。
树最大就是n个点,那么这个点最大的插入次数不会超过 logn 次。
这样,本题就可以用这种方式求解了。
每个叶子节点,建一个包含自己的平衡树。
非叶子节点,从子节点中选一个点数最大的,将它的平衡树作为自己的平衡树,再将其它子节点的平衡树合并到这个平衡树中。
合并的过程查找是否有匹配的值并更新答案。复杂度O(nlognlogn)。
自己生成了一些随机大数据,比点分治要稍慢一些,但是在hdu提交居然要比某些点分治更快,2000+ms。
数的逆元要在开始时预处理,不然会悲剧。
具体看代码吧:
#pragma comment(linker,"/STACK:102400000,102400000")
#include
#include
#include
#include