会动的动态树全解.doc

  1. 1、本文档共8页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
“会动的动态树”这种说法最早出现在nehzilrz神犇的blog里。 link cut tree是解决动态树问题的有力武器之一。他的特点是非常好写,一般来说100行左右就可以实现很多功能。 但是,如果只是解决一些“不动树”上的统计问题,动态树就有点大材小用了。 会动的动态树并不常见,原因是这东西没有被普及。但是在各种比赛中,由于功能强大,它被广泛地应用在骗分程序中。 ? (下文中的Access操作等价于某些论文中的Expose操作) 说几道裸题 SDOI 2008 cave? 这题要求支持link cut findroot三个操 由于link cut的存在 各种离线算法 分块算法都很难解决 本题的标准做法就是动态树(当然那些暴力和并查集。。。我就不说啥了。。。) 首先考虑findroot 这个是非常简单的 access一个点 然后在他当前所属的splay中不停往左走 这个非常显然 cut操作也是很简简单的 主要是要把x(儿子), y(父亲) 放到同一颗splay中的相邻位置 那么我们先access(x) 然后splay(y) 这时候x在y的右边 (而且y的右子树只有这一个点) 此时断开x和y的连接即可 link就有些麻烦了,原因是x点有可能已经有一个父亲了,由于树中父亲的唯一性,你不可能给他安上第二个父亲 这时候就需要一点措施来保证x没有父亲 做法是access(x) splay(x) 在x上打一个翻转标记 注意到打翻转标记之后 当前链上的父子关系全部倒置 导致x成为了这段链上深度最小的 这时候给他按父亲就很容易了 ? 会动的动态树还有一题就是COCI的OTOCI(当然这题的标准做法是离线,这里不谈) 我一直觉得会动的动态树只需要会上面的即可 但是这几天注意到了一个非常严重的问题 先说说WC2012 mst一题的30分 也就是只能-1边权的 由于我比较二 考场上YY了一个非常二逼的做法 排序所有边 将权值相同的一起处理 for each edge 如果当前边连接了两个不连通的点 用一条未染色边link两点 否则 ans += 当前这两点间路径上未染色的边数 同时将路径上所有边置为已染色 权值相同的边处理完毕后 将所有边置为已染色 边权问题可以通过在儿子上记录变成点权 染色的问题可以用标记解决 link操作用动态树解决 看起来是非常好搞的 但是 我考场上写了4个小时多 发现这里面有非常严重的问题 在翻转一段路径之后 以前记录在儿子上的点权现在要记录在父亲上(也就是说新的儿子) 考场上我并没有想出这个问题应该怎么实现 后来咨询了神牛 得出了两种方法 1、将以前的边变成点 (共2 * n - 1点) (from mike_nzk) 2、实时记录当前到路径上儿子的边权 这里主要说第二个做法 路径的改变仅会发生在access的时候 也就说我们在access的时候维护一下这个值就好了 在access的时候 怎么维护呢? 这个问题我并没有太好的解决方案 目前想到的做法是 在access的时候 找到新接上上的子树中深度最小的 这样做的复杂度也许是log^2N 也有可能在某种均摊分析之后变为logN 同时在处理reverse标记的时候 也应该做些许修改 在交换两个儿子的同时 交换向上(到父亲的边权)和向下(到儿子上的边权)的值 附:边权会动树部分代码 ? ? void rev() ? ? { ? ? ? ? if (this == a) return; ? ? ? ? _rev ^= 1; swap(val[0], val[1]); swap(maxv[0], maxv[1]); swap(c[0], c[1]); ? ? } ? ? Tedgeintree go() ? ? { ? ? ? ? push(); ? ? ? ? if (c[0]) return a[c[0]].go(); ? ? ? ? else return val[0]; ? ? }int access(int x) { ? ? int p = 0, q = x; Tedgeintree ret; ? ? while(q){ ? ? ? ? splay(q); ? ? ? ? if (A[q].f == 0) ? ? ? ? ? ? ret = max(A[p].maxv[0], A[A[q].c[1]].maxv[0]); ? ? ? ? A[A[q].c[1]].isroot = true; ? ? ? ? A[p].isroot = false; ? ? ? ? A[q].c[1] = p; ? ? ? ? A[q].val[1] = A[p].go(); ? ? ? ? A[q].update(); ? ? ? ? p = q; q = A[q].f; ? ? }

文档评论(0)

jiayou10 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

版权声明书
用户编号:8133070117000003

1亿VIP精品文档

相关文档