zoukankan      html  css  js  c++  java
  • 模拟测试50

    T1:

      考虑什么时候增加高度对答案有贡献。

      可以发现,当一个建筑物两侧的建筑高度均大于它时(边界除外),才会有贡献。

      所以我们可以先暴力找出所有当前有贡献的区间,压入队列,一个一个处理。

      尝试将一个区间内的建筑物增高,我们发现,对于每个建筑物,每次增加的代价是等差数列的形式。

      将平方差分得到:1,3,5,7......。

      于是我们只要知道增高最下面一层需要的代价,就能算出增加任意高度的代价,这个值初始时均为一,把它存放在b数组里。

      然的后考虑增加一段区间,只有这个区间中所有建筑物的高度相等,且两侧建筑物高度更高,这个区间才能被考虑。

      增加一段区间的高度,每次增加的代价不断升高,而每次的贡献不变,所以增加到代价等于贡献是最优的。

      这个值可以O(1)算出,也可以二分。

      每次动态更新b数组,如果当前区间被填满,就尝试左右扩展区间,同时累加新加入点的b数组作为代价。

      如果当前区间不被填满,扩展到新区间贡献不会增加,而代价反而增加了,所以他一定不是更优的。  

      持续这一过程直到队列为空即可。

      时间复杂度$O(n)$

    T2:

      统计二维区间内点对个数。

      是典型的四维偏序,可以树套树套树......

      然而可以二维莫队A掉。

      时间复杂度$O(qn sqrt{n})$,真实复杂度O(莫队)。

    T3:

      树上直径问题。

      可以先两次DFS求出整棵树的直径。

      然后分别以直径两端点为根做一次树形DP,求出每棵子树内的直径。

      对于没在直径上的点,也做一次类似过程。

      枚举断边,如果断边在直径上,那么就可以用DP值求出新树的最小直径;

      如果不在直径上,就用原树直径和离直径远的点所在的子数的直径更新。

      新直径求法:

        设$l_1$和$l_2$分别为两个连通块的直径,$l$为新树的最小直径。

        $l=max(l_1,l_2,lceil frac{l_1}{2} ceil + lceil frac{l_2}{2} ceil +1)$

      连边一定连的是两个连通块直径的中点,DFS后用深度数组找出来即可。

      时间复杂度$O(n)$

  • 相关阅读:
    谈谈我的经历--【产品设计中遇到的坑0】系列文章的序
    2017.02.04,读书,2017第二本《把时间当作朋友》读书笔记
    读书《重生,七年就是一辈子》
    好剧推荐:This is us
    直播预告:产品设计中不得不知的事情
    高德地图事件与插件绑定
    高德地图基础
    es6 Iterator和for...of循环
    class与class的继承
    JS保留两位小数的几种方法
  • 原文地址:https://www.cnblogs.com/hz-Rockstar/p/11572852.html
Copyright © 2011-2022 走看看