1. 程式人生 > >[BZOJ4828][Hnoi2017]大佬(DP + 單調性)

[BZOJ4828][Hnoi2017]大佬(DP + 單調性)

Address

洛谷 P3724
BZOJ 4828
LOJ #2021

Solution

  • 非常有意思的題
  • 首先求出最多可以用多少天來打傷害
  • 狀態: f [ i ] [ j
    ] f[i][j]
    表示要保證第 i i 天的自信值至少為 j
    j
    ,則前 i i 天內最多可以不刷題幾天
  • 轉移非常顯然
  • f [ 0
    ] [ j ] = 0 , 0 j m c f[0][j]=0,0\le j\le mc
  • f [ i ] [ j a i ] = max ( f [ i ] [ j a i ] , f [ i 1 ] [ j ] + 1 ) f[i][j-a_i]=\max(f[i][j-a_i],f[i-1][j]+1)
  • f [ i ] [ min ( m c , j a i + w i ) ] = max ( f [ i ] [ min ( m c , j a i + w i ) ] , f [ i 1 ] [ j ] ) f[i][\min(mc,j-a_i+w_i)]=\max(f[i][\min(mc,j-a_i+w_i)],f[i-1][j])
  • 求出 n d a y s ndays 表示最多可以用多少天來打傷害
  • n d a y s = max i = 1 n max j = 0 m c f [ i ] [ j ] ndays=\max_{i=1}^n\max_{j=0}^{mc}f[i][j]
  • 然後考慮打傷害
  • 利用 BFS + 雜湊表預處理出一些二元組 ( d , f ) (d,f) 構成的集合
  • 這些二元組 ( d , f ) (d,f) 的意義是可以用 d d 天(包括升等級,提升諷刺能力,以及這 d d 天的最後一天懟大佬, d n d a y s d\le ndays )使大佬的自信值降低 f f
  • 可以發現這樣的 ( d , f ) (d,f) 數量是可以接受的
  • 然後每個大佬分三種情況:
  • (1)不懟大佬,只使用普攻。即判斷是否 C n d a y s C\le ndays
  • (2)懟一次大佬。即判斷是否存在一個二元組 ( d , f ) (d,f) 滿足:
  • f C f\le C (自信值不能為負數)
  • f + n d a y s d C f+ndays-d\ge C (在剩下的至多 n d a y s d ndays-d 內使用普攻)
  • (3)這也是重點:懟兩次大佬
  • 將所有的二元組按照 f f 為關鍵字從小到大排序,然後列舉第一次懟大佬的二元組 ( d 1 , f 1 ) (d_1,f_1) ,然後這時候需要滿足的第二次懟大佬情況 ( d 2 , f 2 ) (d_2,f_2) 需要滿足
  • f 1 + f 2 C f_1+f_2\le C
  • f 1 + f 2 + n d a y s d 1 d 2 C f_1+f_2+ndays-d_1-d_2\ge C
  • 先考慮第一個條件,顯然排序之後合法的 f 2 f_2 是一段字首並且隨著 f 1 f_1 的增大而減小。所以按照 f f 倒序列舉二元組之後 two pointers 維護 f 2 f_2 合法的二元組字首即可
  • 而對於第二個條件,移項後可得
  • C f 1 n d a y s + d 1 f 2 d 2 C-f_1-ndays+d_1\le f_2-d_2
  • 設當前 f 2 f_2 合法的字首是第 1 1 個二元組到第 k k 個二元組
  • 那麼我們要做的就是在前 k k 個二元組中找出一個最大 f d f-d 作為第二次懟大佬的結果
  • 也就是這時候要判斷是否
  • C