zoukankan      html  css  js  c++  java
  • codeforces 1110F

    题解:

    正解做法比较简单,考虑离线之后,相邻两个节点之间的答案是有关系的

    发现从父亲移到儿子后,改变的距离对于当前节点子树内和子树外的是一样的

    所以线段树维护一下区间加减取max就可以了

    另外的做法1:

    过不了,考虑分块

    对连续的叶子分成一个块,维护每个点到这个点的距离,可以多源最短路nlogn

    然后查询的时候零散的要查找两个点之间的距离,这个可以O(1)rmq

    所以块大小设成$sqrt{nlogn}$是$qsqrt{nlogn}$

    理论复杂度1.5e9。。。别想过了

    做法2:

    这个做法可以在线(正解可持久化一下当然也可以),比正解麻烦

    考虑询问一个点x,那么它儿子内的点我们只需要查到根距离最短的就可以了

    然后我们去考虑枚举叶子和当前点的$lca$,这时候我们发现我们只需要查找离$lca$最近的那个点就行了

    但是$lca$暴力枚举只有在树是随机的情况下才是对的

    我们把距离写成$dis[x]-dis[lca]+dis2[lca]$ 其中$dis$表示到根距离,$dis2$表示子树中到它的最短距离

    如果我们知道$dis2$我们就可以维护了

    我们把问题按照$dfs$序和$x$的$dfs$序的大小关系分成两类

    以小于为例

    令$dis2[lca]$为$lca$子树内$dfs$序小于$dfs[x]$到$lca$的最短距离

    那么我们会发现,对于$x$连续的一段祖先,我们考虑它就是考虑$dis2$

    会发现对于不同节点,查询同一个节点$k$的$dis2[k]$是不同的

    所以我们用$dis2[k]$记录原本应该$dis2[fa[k]]$记录的东西,那么就唯一了

    倍增维护

    直到$lca(第一个叶子,x)$这个节点可能是不完整的

    所以要特殊查一下

    查的话可以可持久化线段树合并维护一下每个点子树内dfs为k的值,然后区间查询就可以了

    起始位置如果没有包含所有比$dfs[x]$小的节点也要特殊查一下

    大于同理

    最后复杂度还是$nlogn$的

  • 相关阅读:
    Python文件基础
    Python字符串基础操作
    Python ===if while for语句 以及一个小小网络爬虫实例
    Python 常用函数大体分类
    Atlas安装及配置
    (转)VS无法启动调试:“生成下面的模块时,启用了优化或没有调试信息“
    (转)数据库中视图的作用
    (转)ASP.NET MVC 学习第一天
    (转)介绍几个C#正则表达式工具
    关于textbox.attributes["value"]的问题
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/10356885.html
Copyright © 2011-2022 走看看