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\)单调不降的