Processing math: 100%

2011年4月1日 星期五

Codeforces #56 E Domino Principle

題意﹕給定 N 個多米諾/骨牌,每個骨牌皆有不同的位置 X_1 \cdots X_N 和高度 H_1 \cdots H_N 。若推倒第 i 個骨牌則 X_i+1X_i+H_i-1 以內的所有骨牌皆會倒下。問每塊骨牌可推倒多少個骨牌(包括自己)。 1 \le N \le 10^5 , -10^8 \le X_i \le 10^82 \le H_i \le 10^8

做法當然不能 O(N^2) 枚舉吧。不過先假設 X_1 < X_2 \cdots < X_N ,定義要求答案為 f_i 。設 c_i = j 使得 X_i + H_i - 1 \le X_j, j > i ,即第 i 個骨牌可以接觸到最遠哪個骨牌,如果遇上任何不能推倒的骨牌則表示為 c_i = \infty 。則 f_i 有如下關係﹕


f_i = \begin{cases} \max_{i+1\le k\le c_i}\{f_k + k - i\} & \text{if } c_i \ne \infty \\ 1 & \text{otherwise} \end{cases}


首先,對於任意 i ,查找 c_i 的方法可以用二分搜索。至於計算 f_i ,我們考慮 c_i \ne \infty 的情況。經簡化可得



f_i = \max_{i+1\le k\le c_i}\{f_k + k - i\} = \max_{i+1\le k\le c_i}\{f_k + k\} - i


g_k = f_k + k 。即,我們從範圍 i+1c_i 之間搜索最大的 g_k 值,這就可以用線段樹輕鬆搞定了。算好 f_i = \max_k\{g_k\} - i 後記得為線段樹的區間 [i, i] 插入數值 g_i = f_i + i

說來湊巧,最近與Gagguy聊天起他提起類似問題的做法,之後再做題就剛好遇上此題,所以推導公式還是比較便捷,在此先行感謝Gagguy指點。

沒有留言: