CodeForces - 1366E Two Arrays(组合数学+思维)
題目鏈接:點擊查看
題目大意:給出一個長度為 n 的序列 a ,再給出一個長度為 m 的序列 b ,題目保證序列 b 是嚴格遞增的,我們需要將 a 分割成恰好 m 段,使得每一段的最小值恰好等于 b[ i ] ,問有多少種分割方法
題目分析:我們需要將序列 a 恰好分為 m 段的話,如果知道每一段的左右區間的取值范圍后,根據乘法原理不難算出答案,但又因為每一段的左端點和右端點都是不斷變化的,看似不太好直接求解
仔細分析一下不難看出,因為相鄰的兩段之間是拼接而成的,所以上一段的終點,也就決定了下一段的起點,反之亦然
又因為序列 b 是嚴格遞增的,且需要求的是序列 a 中的最小值,所以倒著處理比較方便
這樣一來我們就可以求出每一個 b[ i ] 對應在序列 a 上的起點的左右區間,然后利用乘法原理計算答案就好了
舉個例子,就拿樣例 1 來說
序列 a 為 {?12 10 20 20 25 30 } ,序列 b 為 { 10 20 30 }
倒著來看的話,如果想要讓 min( a[ l ]?: a[ r ]?) = b[ 3 ] 的話,只能在序列 a 中取 [ 6 , 6 ] 這段區間,這樣一來,b[ 2 ] 終點的位置就確定為 5 了,看一下 b[ 2 ] 的起點,可以選擇 3 也可以選擇 4 ,即在序列 a 中選擇區間 [ 3 ,?5 ] 和 [ 4 , 5 ] 都可以滿足 min( al : ar ) = b[ 2 ] ,此時因為 b[ 1 ] 的起點一定是位置 1 ,而 b[ 1 ] 的終點已經由 b[ 2 ] 的起點決定了,所以這個樣例的答案為 2?
到這里可能會有一個疑問,假如 b[ k + 1 ] 起點的選擇范圍是 [ x , y ] ,b[ k ] 當前選擇的起點為 z?,正常來說當 b[ k + 1 ] 這段選擇的起點為 x 時,b[ k ] 這段選擇的區間是 [ z : x - 1 ] ,這里的 min( a[ z ] : a[ x - 1 ] ) = b[ k ] 是顯然的,那么當 b[ k + 1 ] 這段如果選擇的起點是 x + 1 時,如何保證 min( a[ z ] : a[ x ] ) 這段也是 b[ k ] 呢?因為之前 a[ x ] 這個元素包含在 b[ k + 1 ] 這段中,所以 a[ x ] >= b[ k + 1 ] ,又因為 b[ k + 1 ] > b[ k ] (已知條件),所以 a[ x ] >= b[ k + 1 ] > b[ k ] ,所以 min( a[ z ] : a[ x ] ) = min( min( a[ z ] : a[ x - 1 ] ) , a[ z ] ) = min( b[ k ] , a[ x ] ) = b[ k ]
說道這里就可以想到維護一個最小值的后綴然后判斷了,設 mmin[ i ] = min( a[ i ] : a[ n ] ) ,根據上面的那一段可知,如果我們處理到了第 k 個位置,也就是需要處理第 b[ k ] 段的區間,只要 [ k + 1 , m ] 這些區間都合法的話,那么 mmin[ i ] = b[ k ] 的這些位置都是可以在第 k 段上當做起點的位置,且是連續的,因為數據比較大,所以用 map 離散的記一下數
代碼:
?
?
總結
以上是生活随笔為你收集整理的CodeForces - 1366E Two Arrays(组合数学+思维)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 牛客 - A Simple Game(尼
- 下一篇: CodeForces - 1366D T