题意
有(n)个骨牌呈行排列,高度为(h_i),手动推倒的花费为(c_i)。相邻骨牌距离为(1)。一个骨牌可以被向左或者向右推倒。当第(i)个骨牌被推倒时,会以相同方向推倒与其距离(<hi)的所有骨牌,并产生连锁反应。求推倒所有骨牌的最小花费。
做法
令(L_i,R_i)为将(i)向左/向右推倒,最远被推倒的位置
令(f_i)为利用([1,i])骨牌推倒前(i)张骨牌的最小花费
[f[i] = minleft{ f[L[i]]+c_i, min_{j < i < R[j]} {f[j-1]+c_j}
ight},
]
暴力做是(O(n^2))的
考虑求(L_i),若(i)向右推,能推倒(x),则必能推倒(L_x)
枚举(i=msim 1),用单调栈维护能推倒(i+1)的位置。单调栈自栈顶至底,为序列上从左向右的位置,显然其(L_i)也是单调不增的(拱状)
求(R_i)同理
求(f_i),单调栈内维护自顶至底,能推倒(i-1)的位置,从右往左,(f_{x-1}+c_x)单调不降的