NOIP模拟59

T1:

  首先O(n^3)非常好像,O(n)枚举以i点为最高点,于是问题转化为求

min sigma(hj - (x - |i - j|))其中hj为j位置高度,x为钦定i点的高度,x  - |i - j|即为j位置要求高度

  首先考场上最后想出做法为:利用分块,提取变量x并设k = x - |i - j|

 原式转化为sigma |k - x|,发现讲绝对值函数图像放到坐标系中,则总函数为单峰函数,于是

可以二分x,那么现在问题为如何计算sigam |k - x|,分类讨论k >= x 与 k < x 两种情况,于是

可以利用经典的分块做法:块内排序,在预处理与处理散块时sort维护k的大小关系,查询时

通过lower_bound查询,并通过维护块内前缀和O(1)计算,然而时间复杂度较悬,需要卡常

  正解同样是利用分类讨论拆绝对值,首先对于i左右两侧分类讨论去掉|i - j|,然后考虑

拆式子观察一下:|hj - j - (x - i)|,|hj + j - (x + i)|,基本思想为同类归并,于是发现问题结构非常

相似,我们只需要维护两部分即可,做法为在i两侧分别建立两棵权值树状数组(离散化维护)

维护前缀和与前缀数量,查询时直接查询即可,i位置移动时,调整两侧树状数组信息即可

  需要注意要卡下界

  正解时间复杂度为O(nlog^2n)

  接下来给出Windzr的神仙做法,时间复杂度为O(nlogn)

  上述两种做法的核心在于通过推式子,观察出单峰函数的性质,在考虑如何维护整体求值

主要是利用下标与数据结构拆绝对值维护式子

  Windzr的做法核心在于观察出问题另一关键,即问题要求移动次数最小,那么考虑事实上

移动次数只与基准线上下两侧的方块数有关,而与上下两侧方块高度无关,于是考虑在什么情况下

移动次数最优,显然为上下两侧方块数接近n >> 1时最优,于是同样O(n)枚举i为最高方块位置

设up,down分别为基准线上下两侧方块数,

那么首先卡定下界并Check 此时若down >= up则直接计算答案,否则,根据上述理论

我们设x为基准线还需要向上移动x个方块,那么最优策略显然为:

down + x = up - x,解得:x = up - down >> 1

  显然通过预处理的排序,我们可以O(1)计算移动位置,那么现在关键点就在于如何Check与计算答案

同样的做法,利用权值类型数据结构维护前缀和与前缀数量,以此Check与计算

  简言之,Windzr做法核心在于观察出题目的性质,将枚举具体最高高度转化为基准线的移动,省略

了三分的log并且常数较小。 

T2:

  正解高精度小数,并无意义,问题核心在于观察矩阵填数的规律总结出对数级数学式计算
T3:

  单调栈原题,转化题意通过李超线段树维护

  对于单调不降的部分分通过单调指针维护即可,当i劣于i +1时将i出栈即可

T4:

  问题在于对问题观察于思考不足,n点n边,出度为1,显然为内向基环树森林,

朴素做法显然为枚举所有点作为路径端点向前延伸k的长度,时间复杂度为O(n^2)

O(nlogn)做法为通过倍增优化延伸过程,O(n)做法为考虑要覆盖一个点有k种情况

那么枚举所有经过该点的k条路径即可,时间复杂度O(k * n / k) = O(n)

上一篇:面试题59-I:滑动窗口的最大值


下一篇:MySQL:DDL之常见数据类型(三)