1. 程式人生 > >Hackerrank: Week of Code 36

Hackerrank: Week of Code 36

err .com nbsp 右上角 斜率 當前 常數 最小 tar

Cut a Strip

題目簡述:給定$n \times m$的矩陣$a[][]$,要求選擇一個$x \times 1(1 \leq x \leq k)$的(連續)子矩陣並清零後,找到最大和的(連續)子矩陣。

數據範圍:$1 \leq n, m, k \leq 380$。

題解:

子矩陣可以用四個參數表示$(x_1, y_1, x_2, y_2)$,其中$(x_1, y_1)$是其左上角,$(x_2, y_2)$是其右上角。

我們枚舉子矩陣的$y_1$和$y_2(1 \leq y_1 \leq y_2 \leq m)$,令$c[i] = a[i][y_1]+\dots+a[i][y_2](1 \leq i \leq n)$。

接著枚舉子矩陣經過的某行$x(1 \leq x \leq n)$,則經過第$x$行的子矩陣的最大和為

($c[1], \dots, c[x-1]$的最大後綴和)+($c[x+1], \dots, c[n]$的最大前綴和)+(把$a[x][y_1], \dots, a[x][y_2]$中連續不超過$k$個值清零的最大和)

前兩個可以預處理得到,關鍵在於第三個部分。

註意到

(把$a[x][y_1], \dots, a[x][y_2]$中連續不超過$k$個值清零的最大和)=c[x]-($a[x][y_1], \dots, a[x][y_2]$中連續不超過$k$個的最小和)

後者可以利用單調隊列求得。

時間復雜度$O(n^3)$。

註:單調隊列求數組$a[1], \dots, a[n]$的長度不超過$k$的連續子數組最小和。令$s[i] = a[1]+\dots+a[i]$表示其前綴和。

即需依次對每個$1 \leq i \leq n$,求

$$ \min_{i-k \leq j \leq i} \{s[i]-s[j]\} = s[i] - \max_{i-k \leq j \leq i} \{s[j]\} $$

從而維護區間$[i-k, i]$的最大值即可。

Expert Computation

題目簡述:依次給出$n$個二維點$(x[i], y[i])$以及$1 \leq z[i] \leq i$,且$x[i] < x[i+1]$嚴格遞增。強制在線依次回答

$$ \max_{1 \leq j \leq z[i]} {x[j]*y[i]-y[j]*x[i]} $$

數據範圍:$1 \leq n \leq 1,000,000.$

題解:

先不考慮強制在線,即允許離線回答,則可把詢問按照$z[i]$從小到大排序,然後依次維護下凸殼,回答詢問時,由於下凸殼斜率單調遞增,二分答案即可。

若強制在線,則可持久化維護下凸殼即可。但$n$很大,常數以及空間復雜度承受不了,只能另辟蹊徑。

註意到$x[i]$嚴格單調增,故所維護的下凸殼的各個歷史版本(history version)中,每個點(如果這個點在當前下凸殼上的話)在下凸殼上的前驅是【固定】的。

對每個點,倍增地維護這個點的$2^k$次前驅,如$pre[i][k]$就可表示第$i$個點的$2^k$次前驅。

二分答案時利用倍增特點,可在$O(\log n)$復雜度內解決。

時間空間復雜度均為$O(n \log n)$。

Hackerrank: Week of Code 36