●BZOJ 1767 [Ceoi2009]harbingers

 

题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=1767

题解:
斜率优化DP,单调栈,二分

定义 DP[i] 表示从 i 节点出发,到达根所花的最少时间。
同时既然是一棵树,那么裸的转移还是比较容易想出来的。
$DP[i]=min(DP[j]+(dis_i-dis_j)V_i)+W_i (j是i到根的链上的节点)$
$\quad=min(DP[j]-dis_j*V_i)+dis_i*V_i+W_i$
其中 dis[i] 表示 i 节点到根的距离。
转移方程的意思就是i号点的邮递员走到j号点,然后j号点的邮递员继续走向根。


考虑优化:
假设对于当前计算的DP[i],有两个转移来源点:k,j,同时dis[k]<dis[j],设j点比k点优。
那么有:$DP[j]-dis_j*V_i-(DP[k]-dis_k*V_i)<0$
则: $\frac{DP[j]-DP[k]}{dis[j]-dis[k]}<V[i]$
如果令 Slope(j,k)=$\frac{DP[j]-DP[k]}{dis[j]-dis[k]}$
那么得到结论,如果 dis[k]<dis[j],且Slope(j,k)<V[i]的话,则j点优于k点。
同时如果存在三个转移来源点:k,j,i,满足dis[k]<dis[j]<dis[i],
同时Slope(i,j)<Slope(j,k),则j点无效。
所以对于每个来源点二元组(dis[j],DP[j]),只需要在平面上维护一个下凸壳即可。


值得注意的地方:

1).注意到DP时是在DFS遍历树时进行,所以这就保证了dis的单调递增,
但是V[i]却不单调,所以要用单调栈一个下凸壳,并在其中二分最优转移来源点。
2).由于是在树上进行,所以从某个节点回溯之后,要把当时它插入单调栈时造成的影响消除。
具体做法是:
进入该节点时(已经计算出其DP值)
二分当前点应该在单调栈中插入的位置p,记录该位置之前的信息以及栈顶位置,
然后直接把该点放在p位置,并将栈顶移到p位置。
离开该节点时,再把之前修改的东西全部复原(还原单调栈中p位置的信息,还原栈顶位置)。

代码:

 

 

  

 

posted @   *ZJ  阅读(427)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示