2012年5月11日 星期五

Codeforces Round #119 (Div 1) A~C

表現差強人意,希望下次能再做得好點 :-)

A: 給了兩個$1\cdots N$的排列,對於任意一個排列,可以取出最右邊的數字並可以放在餘下數字中任意位置(除了不能原封不動)。問最少需要多少次操作才能把排列$A$變成排列$B$。良久後才發現如果$A_1, A_2, \cdots, A_p$的相對次序在$B$中並沒有改變,則只需要把剩下$N-p$個數字按插其中即可。答案就是找出最大的$p$並輸出$N - p$。

B: 給了$M$種車輛,並且給了第$i$輛車在一個$N$個城市之間的行走時間。現有$R$場賽事,每場賽事表示要從$s$城到$t$城的最短路,而且只能允許中途轉換最多$K$次車輛。

基本上我看漏了很多東西…首先,$R \le 10^5$,表明最短路需要預計算。其次,$K \le 1000, N \le 60$其實不太可能轉車$1000$次吧?即是其實$K$最多只有$N-1$而已。知道後其實題目是在層圖上做所有點對的最短路。首先固定一種車輛求最短路,然後迭代$N-1$次在層圖上再做Floyd-Warshall即可。

C: 題目給了$N$點及$M$條路,然後在$K$個不同的點上皆放了指示牌。每個指示牌只能顯示長度$q$的路線,問從$s$到$t$,$q$最少是甚麼?保証點$s$一定有路牌。

首先想到的是二分找$q$吧。不過固定了$q$,怎樣才能判斷$s$可以到達$t$?這問題好像和為網絡封包找最少的ttl差不多。不過想到的是直接用BFS,然後記下通過一點時還餘多少步。這樣一來好像跟Shortest Path沒分別,而且狀態一共有$O(Nq)=O(N^2)$個,好像不行。提交時也不能過pretest,以為算法錯了。怎料事後發現自己初始餘下步數的數組為$0$,即是剛好剩一步便到終點的話便沒法更新,改了初始值是$-1$後便AC了。到現在我沒法証明這算法的Worst case complexity…總之應該很快就是。

2012年5月9日 星期三

Topcoder SRM 542 Div 1 Easy + Medium

Easy: 題意非常簡單,給定$X\times Y$的格網,問多少三角形$\triangle ABC$使得以下條件成立。

1) $A, B, C$的縱座標必須各不相同。
2) $A, B, C$的橫座標必須各不相同。
3) $\triangle ABC$的邊長必須介乎$T_\min$與$T_\max$之間。

任意兩點$(X_1, Y_1), (X_2, Y_2)$的距離定義取曼哈頓距離,即$|X_1-X_2| + |Y_1-Y_2|$。

已知$X, Y \le 4000$,$2 \le T_\min \le T_\max \le 20000$,求有多少個符合條件的三角形並取除$1000000007$的餘數。

利用窮舉肯定不可行,$O(X^3Y^3)$無望。從題目特質入手。條件(1)和(2)似乎沒有甚麼特別,似乎保証三角形必定是proper triangle,但卻沒有把題目變得更容易。條件(3)好像也沒有特別作用,但如果定義$F(k)$為三角形的數量使得長度最多為$k$,則在可以著手求$F(T_\max) - F(T_{\min-1})$。不過題目依舊沒有容易很多。

唯一著眼點是曼哈頓距離。可以得出任意三角形在曼哈頓距離的情況下必如下圖﹕


其周界即相等於平行縱橫軸的最小包含長方形周界,長度為$2(\Delta_x + \Delta_y)$。由此可知我們其實想求所有可行的$\Delta_x$和$\Delta_y$使得
\[T_\min \le 2(\Delta_x+\Delta_y) \le T_\max\]
即表明我們毋需枚舉三點,只需枚舉$\Delta_x$及$\Delta_y$即可,當中$\Delta_x$及$\Delta_y$包含的三角形數即屬答案一部分。

那麼顯而易見對於$\Delta_x$($\Delta_y$亦然),必須有兩點的橫座標相隔$\Delta_x$,第三點則任意取其中間的點。而根據橫座標最多$X$點,則$\Delta_x$的長度有$X-\Delta_x$種取法,第三點則有$\Delta_x-1$種取法,因此符合條件的所有橫向座標有$(X-\Delta_x)(\Delta_x-1)$種。同埋縱向座標有$(Y-\Delta_y)(\Delta_y-1)$種。

可能你會覺得奇怪,為何分開縱橫軸計算?看如下圖片便知﹕



只要我們知道縱軸三點和橫軸三點,則可以構造$6$個不同的三角形。因此,對於$\Delta_x$及$\Delta_y$,只要符合條件(3),一共有$6(X-\Delta_x)(\Delta_x-1)(Y-\Delta_y)(\Delta_y-1)$個三角形。

因此本題能在$O(XY)$時間計算答案
\[\sum_{\Delta_x=2}^{X-1}\sum_{\stackrel{\Delta_y=2}{T_\min \le \Delta_x+\Delta_y \le T\max}}^{Y-1} 6(X-\Delta_x)(\Delta_x-1)(Y-\Delta_y)(\Delta_y-1) \bmod{1000000007}\]

Medium: 給了$N$個長度恰好為$L$且互不相同的字串,以均等機會隨機取一任意固定排列,然後為字串依排列重組,並為$N$個字串排序,問每個字串排首位的概率是多少。$1 \le N \le 16$,擺明是Exponential Time動態規劃吧。不妨設$F(B, i)$表示以集合$B$內的字串$s_i$經排序後排首位的概率。可以知道對於$s_i \not\in B, F(B, i) = 0$,而且$F(\{s_i\}, i) = 1$。由於字串互不相等,因此必定存在位罝$p$使得存在$i, j$並且$s_{ip} > s_{jp}$,即存在$s_{ip}$不可能再成為首位。假設$B'$包含了該種字串,枚舉$L$個字串位置後有$K$個可排除集合$B'_1, B'_2 \cdots B'_K$,因此得遞迴公式
\[F(B, i) = \frac{1}{K}\sum_{B' = B'_1, \cdots B'_K}F(B-B', i)\]

並可於$O(2^NL)$計算答案$\{F(S, 1), F(S, 2), \cdots F(S, N)\}$,其中$S = \{s_1, \cdots s_N\}$。

有一個小問題﹕為何不用考慮排除集合為空集的的情況?如果考慮了後則會有$F(B, i)$依賴自身狀態的情況?
答案﹕Principle of Deferred Decision。

另外,我們亦可以憑如下關係得到同樣答案﹕
$\begin{align*}
F(B, i) &= \frac{1}{L}\sum_{B'}F(B-B', i)\\
F(B, i) &= \frac{1}{L}\sum_{\stackrel{B'}{B'\ne \emptyset}}F(B-B', i) + \frac{1}{L}\sum_{\stackrel{B''}{B''= \emptyset}}F(B-B'', i)\\
F(B, i) &= \frac{1}{L}\sum_{\stackrel{B'}{B'\ne \emptyset}}F(B-B', i) + \frac{L-K}{L}F(B, i)\\
\frac{K}{L}F(B, i) &= \frac{1}{L}\sum_{\stackrel{B'}{B'\ne \emptyset}}F(B-B', i)\\
F(B, i) &= \frac{1}{K}\sum_{\stackrel{B'}{B'\ne \emptyset}}F(B-B', i)\\
\end{align*}$

2012年2月27日 星期一

PCOI CCC 2012 Warm up contest

是次比賽共五題,亦是當年小弟第一次參賽CCC的題目。

A: 沒甚麼難度,是一道小心編寫的「輸出格式」題。

B: 沒甚麼好注意的,簡單的邊界檢查題。寫的時候可以考慮一行過的寫法﹕假設橫軸長度是$c$,而位於橫軸坐標$x$需要位移$d_x$,則可以透過一道公式更新位置\[ x := max(min(x + d_x, c), 0)\]緃軸亦然。

C: 直接依據題目要求計算矩陣的張量積即可。雖然直觀算法是$O(N\prod n_i\prod m_i)$,其中第$i$個矩陣是$n_i\times m_i$,但是倒是沒有大數據…就是做。

D: 簡單點說,就是給定一個深度優先的遍歷表,求與廣度優先的遍歷下的來回時間的相差。可以肯定的是廣度優先的遍歷只受最長路影響。假設最長路是$K$,答案則是$10(N - 2K)$。注意﹕題目沒說過起點的名稱必定是Home

E: 給定$N$個遊戲得分順序,求每場遊戲下的排名的平均數。直觀算法是$O(N^2)$,不用說肯定會超時。有三種做法。

(i) 利用平衡二叉樹進行插入及查找,可以用伸展樹,時間複雜度是$O(N\lg N)$。
(ii) 留意我們根本不用「實時」計算排名。若果按分數排序,並且為分數順道記錄其遊戲時序,則順序枚舉遊戲時查找分數比它高且時序比其要早。設符合遊戲數是$K$則其排名是$K+1$。如此一來可以用線段樹查找時序較早的遊戲數量,計得排名後把現時遊戲更新到該線段樹上。由於是Point update Range query,實際上也不是太難寫。
(iii) 同(ii),直接用Binary Indexed Tree,兩行代碼,方便快捷。

注意輸出浮點數往往會有精度問題。例如$44.445$會有機會存成$44.4449999999\cdots$而最終再取位下輸出成$44.44$(然而希望的是得到$44.45$)。為了解決類似情況,可以考慮用「無限小數」修正並輸出。例如該浮點數是$x$則輸出$x+\epsilon$,其中$\epsilon = 10^{-9}$足夠了(記作eps = 1e-9)。

2012年2月19日 星期日

CCC 2012 PCOI-TFT

應該是第一次寫這種不公開的比賽的貼文吧。
今次比賽4道題,只中兩道題是以前賽事的題目,只有兩題我本人出的。

A. 題目問的是給了$M$個立方體箱子,能放進$N$個預定大小的箱子中體積最小的哪個。明顯地只需要把所有箱子按三維坐標排序測試即可。

B. 問一個圓心在原點,半徑為$N$的圓形,當中覆蓋了多少個整數點。留意普通枚舉不可行。亦可以留意對稱性之下只需求一個象限的答案(不包含縱橫軸以免造成覆算)。在一個象限的答案可以依坐標$(N-1, 1)$ 開始不斷求算直至某點$(N-1 - \delta_x, 1)$在圓內,然後以$(N - 1 - \delta_x, 2)$ 開始重新計算,直至移動到$y = N$為止。假設該象限有$K$個點在圓內,則答案是$4(K + N) + 1$。

C. 給了$N$個整數的數列$A$,並且給定了$K$個區間,分為是$[a_1, b_1], \cdots [a_K, b_K]$,問每個區間之下求$\max_{i \in [a_i, b_i]}A_i$。另外,不存在$a_i < a_j \le b_j < b_i$,而且$a_i$必定按遞升次序。直觀的做法當然是可以用線段樹,但就沒有利用到最後給定的條件。留意重新理解這個條件的話,便可以知道,只需按在相同$a_i$的值下按$b_i$重新排序(簡單的counting sort即可)其實必定保証了當按左至右查找答案時,第$i$個詢問完成等價於任何第$j < i$個詢問也必定完成。這是RMQ的特例,稱為Sliding RMQ。根據這種特性其實用Monotone Deque即可完成本題。時間複雜度是$O(N)$。

D. 問一條二元字串$s$經過最少多少次修改後變成反對稱。修改包括「增、刪、換」,反對稱則是指字串倒轉寫後每個字元與倒轉前不一樣。一道經典動態規劃題。假設$f(x, y)$是對原字串第$x$至$y$位作修改後,最少需要多少次修改才成為反對稱字串。則有如下狀態轉移方程﹕
\[ f(x, y) = \begin{cases}
0 & \text{if } x > y .\\
1 & \text{if } x = y .\\
f(x+1, y-1) & \text{if }s_x = s_y .\\
\min\{f(x+1, y), f(x, y-1), f(x+1, y-1)\} + 1 & \text{otherwise.}\\
\end{cases}\]
答案是$f(0, N-1)$。時間複雜度則是$O(N^2)$。