Hackerrank: Week of Code 36
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