CF1131G

题意

\(n\)个骨牌呈行排列,高度为\(h_i\),手动推倒的花费为\(c_i\)。相邻骨牌距离为\(1\)。一个骨牌可以被向左或者向右推倒。当第\(i\)个骨牌被推倒时,会以相同方向推倒与其距离\(<hi\)的所有骨牌,并产生连锁反应。求推倒所有骨牌的最小花费。

做法

\(L_i,R_i\)为将\(i\)向左/向右推倒,最远被推倒的位置
\(f_i\)为利用\([1,i]\)骨牌推倒前\(i\)张骨牌的最小花费

\[f[i] = \min\left\{ f[L[i]]+c_i, \min_{j < i < R[j]} \{f[j-1]+c_j\} \right\}, \]

暴力做是\(O(n^2)\)
考虑求\(L_i\),若\(i\)向右推,能推倒\(x\),则必能推倒\(L_x\)
枚举\(i=m\sim 1\),用单调栈维护能推倒\(i+1\)的位置。单调栈自栈顶至底,为序列上从左向右的位置,显然其\(L_i\)也是单调不增的(拱状)

\(R_i\)同理

\(f_i\),单调栈内维护自顶至底,能推倒\(i-1\)的位置,从右往左,\(f_{x-1}+c_x\)单调不降的

posted @ 2020-05-19 14:25  Grice  阅读(121)  评论(0编辑  收藏  举报