網頁

Saturday 31 December 2011

URAL 1557 - Network Attack

題目一句講完:
給出一個無向圖 G (可以有重邊/自環), 問有多少種方法 remove 2 條 edge 使得 G 變成 disconnected

一開始從 build BCC 的方向想, 可分為兩個 case: remove 一條 bridge + 任意, 以及在同一個 BCC 內 remove 兩條
不過想不到怎樣做 case2, 所以放棄了
後來想到可以用 DFS tree, 因為 tree 比較容易處理

先找出 G 的任意一棵 DFS tree
首先, 要使得 G disconnect 的話至少要 remove 一條 tree edge, 這樣就限制了很多可能性
以及, DFS tree 的其中一個特性是沒有 cross edge

Case 1: remove tree edge + remove back edge

很簡單, 只要記錄 subtree 的連通性便可以
Compute dp[x][y] = x 的 subtree 中有多少條 back edge 連到 y
便可以知道 x 的 subtree 有沒有連到外面, 如果是 0 條 edge 或 1 條 edge 就有方法做成 disconnect

Case 2: remove tree edge + remove tree edge

首先再分成 2 個情況: 兩條 tree edge 有沒有 ancestor 關系
如果沒有就很簡單, 做法和 case 1 十分類似



如果有的話則比較麻煩, 如圖, 紅色是想 remove 的 edge, 現要判斷綠色部份是否有連到藍色部份
而且要在 O(1) 內判斷
其實可以改變一下 dp[][] 的定義, 利用沒有 cross edge 的特性, 可知 x 的 subtree 只會連到 x 的 ancestor
dp[x][y] = x 的 subtree 中有多少條 back edge 連到 x 的第 y 層 ancestor
再使用 partial sum, 則可快速判斷

總時間為 O(N2+M)

Monday 26 December 2011

Sem 3 之後..

Sem 3 終於完了(不計315 asg4 的話), 就寫寫總結吧
基本上功課沒有想像中那麼多, 可能因為沒有 318 的關係, 不過也有數天是特別忙的, 只是通頂次數比想像中少
不過真正忙的是加上每星期 14+小時的 ACM training, 令到這個 sem 非常充實

CSCI3230 Fundamentals of Artificial Intelligence - 莫明奇妙, 無法解釋

上了第一個星期之後就沒再上過堂.. 因為發現 lecture 的水份成份特高, 難以 get 到佢想講咩
slides 也是一樣, 寫得難以理解~
功課也很少, 只有一份 written + prolog + nn project

Final 也是年年一樣, 用 NN 的說法, 就是不斷用 past paper 做 training set
總括來說這個 course 十分無聊 + 頹, 唯一的得著就是見識一下 prolog 吧


CSCI3170 Introduction to Database Systems - 頹廢上堂, 頹廢結尾

317 可說是最「沒特色」的一科: 難度, 功課量等都是平均的水平~
開頭是 ER/SQL 等, 因為 AL 教過的關係, midterm 輕鬆高分
後半段雖說不上十分有趣, 但也不會悶, 雖然因為種種原因而開始走堂
B+ tree, recovery, locking 等都沒有上堂, 不過溫 final 時也不用花很多時間便看明, 不過最後還是炒了

功課可算是輕鬆, 不過 317 跟 323 有點相似的地方就是 slides 都很莫明奇妙
317 的 slides 那些 point 給人感覺就是隨便放在某一個位置上, 看的時侯還要想像它們的順序
還有就是 Ada Fu 講書會愈講愈細聲, final 有 amendments 時我估有半數的人是聽不到的
總括來說這科還是頹頹的過去便算了


CSCI3150 Introduction to Operating System - 燃燒時間, 燃燒肝臟

如果 315 沒有功課的話我對這個 course 的評價一定大升
雖然其實功課也很有意義, 會學到很多, 但每次一趕 deadline 又做不到又要通頂就會很燥
雖然對 OS 沒有強烈的興趣, 但內容其實還是挺有趣的, 不得不說 mole神教得十分好~
不過每次聽完也是似明非明的 status, 到了做功課和 final 又會覺得自己一事無成

一共有 4(5) 份功課, 全部都是 kernel hacking, 每份功課要打的 code < 100 行, 但是每次都要花數天去做..
最過份的是最後一份在 1 月才 dead, 放假也要做功課
總括來說對我來說 315 快快完結就好了


CSCI3160 Design and Analysis of Algorithms - 自信十足

完全沒有上堂的一科, 原因也不完全是因為學過 (除了 FPT), 最主要的原因還是因為是在九半
所以到現在連蔡雷震的真人也未見過..
不過還是要強調, 玩了幾年 OI/ACM 其實真的可以不上堂, 只要看看 slides 便可以去應試~

功課對我來說不難, 不過有時會很長, 有一份功課做了足足 10 頁紙, proof 也不用 formal 地寫
聽聞以前是會 kill 的, 現在變得不會, 導致 midterm/final 十分頹, final 還有一小時 check 卷~
總括來說就是讀得十分輕鬆


CSCI3130 Formal languages and automata theory - Inspiring, Exciting, Interesting

這個 sem 最有趣的 course, 除了去比賽全部堂都有去上~
功課雖然要寫很多, 但是做起上來還是很有趣的, 也有挑戰性, 很久沒有認真地去做功課
由頭到尾等都十分精彩, 最尾的 zero knowledge 更是一個完尾的句號~
還有就是 Andrej 教得十分好~ 上完堂後唔使點準備都可以就咁去考 final (雖然又炒了)
目前是由 yr1 以來最喜歡的 course~

經過 intern 和這個 sem, 終於發現原來還是喜歡不用打 code
雖然每次做完 315 都很有成功感, 但沒有 313 那種 inspiring 的感覺

Sunday 18 December 2011

COCI Contest 3 + SRM 527

COCI 2011/12 Contest 3: 10pm - 1am
SRM 527: 1am - 2.30am

就係咁, 連續打左 4 小時 code..

COCI:
除了 q6 其它基本上都立即想到做法
q2 題目寫得很差, 最後要靠估的
q3 第一次做 dice 題, 沒有經驗 hard code 這些東西, 寫得不是太好
q4 用 lower_bound 解決之
q5 很 standard, 做法是 pre-order traverse 一次, 然後每個 operation 便可以轉化成 1D 的 range update, 再用 BIT 做之, 由於 N 很大所以用 iterative 的 DFS
q6 其實是要找最大的 'gap', 即最長的等待時間, 不過想不到怎樣很快找 gap, 最後嘗試水分不成功


SRM:
今次打得挺順利的.. 基本上很快便想到做法
275: 用 dp[x][y] = 處理了 node 1..x, cover 了 node 1..y 的 maximum score
475: 上至下, 左至右試 '?', 再用 bipartite matching verify 之

Rating: 21322241 :D

Saturday 17 December 2011

URAL 1128 - Partition into Groups

由於想不到, 所以看 solution

做法很簡單, 先隨便 partition
然後 while child x has ≥ 2 enemies in his group, move child x to another group

Let badness = | { (x, y): x, y are enemies and lies in same group } |
可見 badness 在一次 operation 後會下降至少 1
而 initial badness ≤ 3N, 及 0 ≤ badness
所以一定有 solution, 而且 O(N) 找到

Monday 12 December 2011

Sem 3 Final + HKOI Final

終於過了這個 sem 最辛苦的 2 天 (3 個 final + 第 3 天 = HKOI final)
雖然還有 1 個 final + 2 份 asg, 但開始有心情渣灘了..

今年終於可以在 final 食花生, 原來食花生是很開心的
雖然現在打 code 己經沒有了當年那種膽戰心驚的感覺, 但終於覺得這年的 training 自己還是有進步的
結果我已經知道了, 可以說的是, 多打 code 一定沒有壞處

目前來說沒有一個 final 是滿意的, 完全沒有 midterm 那種輕鬆高分的感覺
希望出來結果不會太差吧..

Wednesday 7 December 2011

stl 中 vector 的 resize

溫 315 溫到 memory 的部份, 突然想起很久以前就想知道 stl::vector (下稱 vector) 是怎樣寫
為甚麼 vector 可以這麼神奇, 能不受限制地 push_back, 又可以快速地 random access?

最合理的解釋便是一開始預留了 memory 給那條 vector, 當不夠用時便 malloc 更多的空間
然後當然很好奇想知道每次預留多少空間 (估計是 4K), 一於寫個 program 試下

vector<int> a;
int *expect, *real;
a.push_back(0);

for (int i=1; i<1000; i++){
   expect = &a[i-1] + 1;
   a.push_back(0);
   real = &a[i];
   if (expect != real) printf("Reallocated at %d\n", i);
}

expect 是下一個 push_back 後預計的 address, 照理說如果 reallocate 了的話 real 和 expect 便應該不一樣
run 得到以下 output:

Reallocated at 1
Reallocated at 2
Reallocated at 4
Reallocated at 8
Reallocated at 16
Reallocated at 32
Reallocated at 64
Reallocated at 128
Reallocated at 256
Reallocated at 512

即是說, 每次 push_back 空間不足, 便會resize 成自身長度 2 倍的空間
假設 resize 的時間是線性, push_back N 次後的時間 = O(N) + O(N/2) + O(N/4) + ... = O(2N) = O(N)
所以 vector 的 push_back 平攤後是 O(1)

Saturday 3 December 2011

VC → HAMPATH

今天看了 VC → HAMPATH, 覺得個 construct 非常巧妙

VC(G, k): exists a k-vertex cover in G?
HAMPATH(G): exists hamilton path in G?

而要做的是, 把 HAMPATH model 去做 VC

由 "cover all edge" 變成 "pass all vertex", 很自然地想到 edge, vertex 互換
想法1: G 的 edge 是 G' 的 node, G 的 node 是 G' 的 edge

問題: 1 個 node 可以連著很多 edge, 但 1 條 edge 只能連著 2 個 node
解決: 每個 node 是 1 條 chain, 即多條 edge




明顯地未完成, 右圖輕易存在 Hamilton path, 但原圖的 VC 最少選 2 個 vertex
最大問題是, 不想條 path 走到一半可以換顏色
現在要加入 VC 中的變數 k: 選取 k 個 vertex, 即要 traverse k 種顏色的路
換句話說, 可以選取 k 條 disjoint path 去 visit 所有 vertex, 而每條 path 的 edge 是同顏色

這時就是最巧妙的一步
目標是把每個點 v 拆成一堆點 v', 並且符合:
1. 只對外連著 2 種顏色的 edge
2. 要走遍 v' 只能是: 選取了顏色1 / 選取了顏色2 / 選取了顏色1, 2

千呼萬喚:




要 visit 圖中的所有點, 有以下方法:




左至右: 只選藍色, 只選紅色, 兩種都選
分別對應一條 edge(u, v), 在 VC 中選取了 {u}, {v}, {u, v}

而且有一點很重要的是, 不能走到一半換顏色
因為若換了的話便一定不能走遍 v'

最後會得到類似以下的東西:




選 1 種顏色 (即選一個 vertex), 就可以走遍它連著的 edge
接下來這步就很簡單了, 因為選 k 個 vertex, 即可 traverse 此 graph component k 次
只要添加 k 個新 node 便可以解決之

References: http://valis.cs.uiuc.edu/~sariel/teach/notes/algos/lec/03_npc_III.pdf

Tuesday 29 November 2011

Sem 3 12/13: 315 Asg3 之後..

因為去 regional 的關係, 加上 sem 尾又多 deadline, 導至 deadline 前幾天才開始做
更確切地說, 是在 deadline 那一天的下午才開始改 code, 完全感受到 deadline 的壓力
幸得 peter 大大的幫助才可迅速完成

很討厭趕 deadline, 而這次更是 deadline 前 2 小時才有初步結果
不過做完後又好像對 spin-lock/semaphore 多了不少認識
我想如果有無限的時間的話也許會比較享受 315 吧..

加上 317 又因為 regional 的關係炒了一份 asg, 沒有了 course grade 3 分, 導致心情十分煩燥
不過 313 總算彌補了種種的不滿 :)
很久沒試過很認真地去做一份功課, 與做 315 的感覺完全相反
欣賞了 SAT → 3SAT, SAT → 3COL 和 Cook-Levin Theorem, 非常有趣 + 精彩
平時很多 slides 看完都不會留下深刻印象, 不過我想這些應該很難忘記吧
過了這麼多年, 總算弄清楚 P, NP, NPC
終於開始覺得這個 sem 不是一事無成..

Tuesday 15 November 2011

CodeForces Contest #94

差不多一個月沒打CF (因為和 training 的時間相撞)
感覺題目的整體難度又提高了

A - 沒看到是 8-dir 寫了 4-dir 所以錯了 2 棍..

D - 感覺有些像 shy tortoise, 建立 freq[] 後由左到右處理, 不斷進行 freq[i+1] -= freq[i]

B - 比以往的 B 難, 做法有點像 suffix array 的思想, 先比較第 1 個位, 然後比較第 2 個位.. 但是 TLE 了, 因為用了 v[] 去表示可能開始的位置, 但其實應該用一條 list[] 去保留便可以, 前者的時間複雜度最差情況會是 O(N2)

C - 花了很多時間才想到可以 x, y 分開做, 得出 cnt[i] = sum{cnt[j] * (j - 1 - i), j > i}, 但仍然是 O(N3), 把式重寫成 cnt[i] = sum{cnt[j] * (j - 1)} - sum{cnt[j]} * i 可降至 O(N2)

今次的題目難度和次序很奇怪, 對我來說, 難度應該是 A -> D -> C -> B..

Sunday 13 November 2011

ACM ICPC 2011 - Kuala Lumpur

比賽前要把背包放在一個房間, 中途看見只有 9 種氣球, 代表只有 9 題, 即是很有可能要以罰時決勝負, 對我們有點不利, 因為我們的罰時一向都不是太好

其實比賽在 9:15 便開始了, 比去年準時很多. 我負責分題目, 感覺上沒有甚麼頹題. 不久後 whh 上 A, submit 後得到 WA.. 此時己經有些燥, 在開始便已經落後人. 幸好第 2 棍便過掉

A - tui (whh, 19 + 1WA)

中途 ff 告訴我 E 的題意, 我一看便知道是一般圖匹配, 這時還覺得挺開心, 因為有武器而且我覺得不會很多隊伍能做到. 不過由於代碼很長, 決定先放在一邊, 和 whh 研究 I, 很快發現用多一支 vector 一定不會使答案變差, 所以 vector 的次序並不重要, 便猜想可以把 vector flip 至第1, 2 象限再處理, 不過不是很確定, 所以交給 ff 和 whh 處理, 我則處理 G - string 的題目, 很快便想到可以用 suffix array (其實用 kmp 便可以), 於是便啪啪啪打武器, 中途和 ff 交替讓他做 H. 寫好 G 後 submit, 返回 WA, 不久後 ff 的 H 也 WA 了, 很差的開局. 約 15 分鐘後發現一些 for loop initilize value 寫錯了, 此時 ff 的 H 也過了

H - dp (ff, 67 + 1WA)

G - suffix array (gg, 74 + 1WA + 1RTE)

此時完全沒有興奮的感覺, 因為很多大學己經拋離我們 (台大好像己經 5+ 題). 此時 ff 和 whh 又沒有其它題目可做, 於是便打 general graph matching 的武器, 其中一行代碼是 g[i][j] = g[i][j] = -1, (馬後炮) 使我有點懷疑武器的可信度.. 不過還是要打, 順利過 sample, submit 後得到 TLE, 便給 ff 做 F (shortest path?) 和給 whh 做 I, 我則把60多行的 code 印出來做人肉 diff..

之後便是差不多一小時的空白, 我的 E 完全找不到 bug, 他們的 F, I 也嚴重卡題的情況 (加起來 WA 了 5 次), 而我隨便 gen 了一個大 case 發現會在一些 do{}while() loop 中 loop 死, 但又找不到 bug, 使我十分焦燥. 大約過了一半的時侯 ff 終於過了 F, 總算有些進展...

F - shortest path (ff, 166 + 2WA)

終於 4 題, 但罰時是在同題數中最高的. 我們的分工是: whh 做 I, ff 做 C, 我則做 B - 在去年的 training 中見過類似的, 做法十分麻煩, 是 segment 內嵌 BIT, 如果之前沒做過的話我也懷疑我寫不出.. 此時腦袋己經十分疲累, 但幸好是第 2 次寫, 故寫得頗順利, 提交卻得到 RE, whh 的 I 也繼續 WA, 愈來愈令人焦急.. 幸好 ff 的 C 一棍過了, 十分慶幸不用 debug C 這種題呢

C - evaluate expression + randomize (ff, 227)

不久發現 lower_bound() 有些位 handle 錯了, 改之, 終於過了 B, 鬆一口氣

B - segment tree + BIT (gg, 234 + 1RTE + 1WA)

之後看之前看錯題目的 D, 認真想了一想後覺得不太難, 便接著做, 是比較像"OI" style 的題目, 當然由我解決掉~

D - adhoc (gg, 260)

這時侯我們仍然有希望可以全清的, 因為可能 E 只是一個小 bug, 加上 I 有很多隊做到, 在剩下的 40mins 我們應該也可以做到. 但愈試 E, 愈是開始覺得是武器出錯.. 他們的 I 好像也試了另一個 approach, 但最終也是過不了.

完場後十分灰, 也不想知道自己的 ranking, 在發現 E 竟然可以用 bipartite matching 水過後更加燥.. 隨手畫一個 case 都可以炒掉 bipartite matching, 怪不得這麼多隊伍過了..

其實以我們的實力 9 題是可能的, 雖然開局很差, 但其實還是有很多機會可以全清 (例如放棄 general graph matching 的武器嘗試水, I 也應該更早放棄 iteration 的 greedy 算法), 不過還是輸了, 感覺十分差

今次分題目不是分得很好, 不過有數題也是有 (x, y) 的坐標 input, 但其實全部都不是"真正"的 geom 來的; 不過對台大這種 "三名高手型" 來說可能沒有甚麼差別吧

今次完全浪費了 whh 的戰力, 大部份時間都在試 I 的錯誤做法 (greedy flip vector), 希望 fuzhou 的題目可以讓 whh 發揮吧

Friday 11 November 2011

Sem3 10/13: Prolog

因為 AI 的關係所以接觸到 prolog
一開始覺得很莫明奇妙, 即使想拿到 list 最尾一格也要搞一大輪, 很躁
功課也完全沒有頭緒, 無從入手
不過得到 david 大大的指導, 逐漸明白其實就是在寫 CFG 的 rules (雖然也很煩)
功課有個 online judge system, 可以大約知道自己寫的對不對, 也是不錯的
總括來說對 prolog 的印象還是正面的

由於要準備武器的關係, prolog 的功課做到 8x 分便放棄了 (無左 course grade 2 分..)
即是說 project 又要努力一點了

其實人身在吉隆坡, 後天便比賽了, 雖說有 59 team 參加, 但仍然是十分緊張
不過每次 regional 過後便要還 assignment 債..

Tuesday 25 October 2011

URAL 1464 - Light

很感動, 搞了幾天終於過了
開始有信心做其它 sweep line 題

詳細算法在 kn 的 blog 有, 都是 sort by angle + sweep line
不同的是我用的是 heap
開頭以為可以用 stl priority_queue, 但在處理 delete 時, 不能像以前 expire + reach top 才 pop, 因為只是存在在 heap 中就會打亂次序
所以只好人手寫一個 heap

在發現無數的 bug (例如離散角度時沒有處理 -PI 和 PI 同時存在等等) 後, 加上無限的 WA, 終於過掉了!
之後再把無用的 code 刪掉, 竟然可以 runtime 第一
雖然其實沒有甚麼大不了, 但還是興奮了一陣子

Tuesday 18 October 2011

SSU School Team Regional Team Contest 2011

好像是 SSU (Saratov State University) 的人出的題目, 類似 SSU 的邀請賽?
Anyway, 由於在 CF 也有同步賽, 在香港時間的下午, 不過星期二等價於 day off (317 + 323 + 323), 於是就在家獨自打
5 小時 10 題, ACM ICPC rules
題目

由於午睡的關係遲了半小時開始..
A-C 都是頹題, 不過 C 看錯了所以錯了一棍; D 寫得不是太好+沒看清題目又是一錯棍; 看到 tourist 跳過了 E 做 F, 便先做 F, 很簡單的計 tree diameter; 看了看 E, game 題, 不懂又不想花時間找 pattern; H 好像不太難, 做法是枚舉所有可行的簡寫, 最多 264 個, 中途可以 prune 掉很多 - 再做二分圖匹配; G 是閱讀理解模擬題, 沒有想像中複雜, 不過沒看到要順序 output 錯了一棍.. 之後寫 E 的暴力看 pattern, 發現原來是很簡單的 pattern, 怪不得很多人很快便過了; J 挺有趣的, 想了想其實是找距離, 所以可以先把所有點 flip 至第一象限再做最近點對, 因為 1-base 又錯了一棍.. 剩下 I, 有點煩膠的 greedy, 一開頭打算寫 dp, 但發現又不用, 只要逐個位試便可以, 但是也是寫得很長, WA 後寫了暴力對拍 debug, 最終在 278 的時侯過了, rank 37

雖然真正比較難的只有 2-3 題, 但單挑還是很有趣的 :)

Thursday 13 October 2011

Team Training 10/10/2011, 12/10/2011

ChengDu 2007

D: simulation by whh
J: 簡單題 by whh
B: AP by gg
- 其實很早就寫完, 不過沒發現伏, 花了點時間把所有情況想清楚
H: 1999題 by faifai
A: partial sum by whh
C: dp on tree by gg
- 寫得很差, 想漏一些東西導至 code 得很複雜 -> debug 困難, 之後重做短了 40 多行
F: state dp by whh
- 好像是插頭 dp, 錯了很多次, 懷疑有比較簡單的做法
E: by gg + faifai
- 和 faifai 討論了一下, 發現原來看穿了就很簡單, 我負責 RMQ 的部份, TLE, 發現可以很簡單地用類似 histogram 的方法降至線性, WA 了幾次後發現是 LL 的問題, 最後 293 + 4 過了

I: 見此
G: 原來用 A* 就可以, check 的時侯只考慮有機會 intersect 的 rectangle


Kuala Lumpur 2010

很難得的接近full team打.. (3人出席時間加起來應該有13小時, 好像是開學以來最多的一次..)
就扮真比賽記錄吧

開始 whh 負責打template, 我分題目, 發現把很多題目都分了給ff. 不久 ff 發現簡單的 B, 瞬切. 我看的 I 很像 Jakarta 的 B, 很快便推到式, 在 ff 做完後便接著做, 過不到 sample, 先給 whh 做 H (因為忘了 output test case number 錯了一棍), 很快找到 bug, 改之, WA 後發現把 test case 數目看成 input size 了.. 改好便過了第 3 題, 暫居榜首 (好像是). 此時 ff 寫 D, 我手上有 F (grid, 可能是 BFS), G + J (geom), 同時 whh 問我 C 是不是很熟面口, 一看發現竟是我 211 project 的題目! 不過由於有太多題目在手加上 whh 好像沒有其它題目做, 便把算法告訴他由他來想細節, 等自己可以專心做我負責的題目. 不久後 D 輕鬆 WA, 由於 debug 不能, ff 便改做好像較簡單的 A, 不過寫到一半又發現 trivial 的 greedy 好像有反例, 和他討論了一下又找不到方法解決. G 是 standard 的二分, 於是便搶先寫, 途中他們發現很多隊過 A, 便覺得應該可以頹做, 結果是可以的. 我的 G 也緊接著 A 過了. 之後好像是 whh 和 ff 交替寫 C 和 D, 突然發現 live archive 的題目和 official site 的 D 是不一樣的! (好似係minor difference), 改後仍是 WA, 而 C 就 AC 了, 便讓 whh 幫 ff 的 D debug, 我做 F (standard steiner tree, 比較麻煩的是 vertex 有 weight). 不久後成功過 D, 我的 F 則 WA, 不過可以用 machine 有效率地 debug, 很快便發現 vertex weight handle 錯了, 改+過之. 此時剩下一半時間和 2 題, 如果不是預先知道題目難度的話應該會覺得很大機會全清的. 分工是我做 J, whh 做 E, ff 則 2 邊協助, 和 ff 討論了一下, 很快便找到不是過 2 點的 case, 便想到一個很複雜的line rotate 算法. 不過 whh 好像對 E 沒有甚麼想法, 便問了一下他的意見, 他覺得過 1 點的話 line 是 fix 的, 我覺得合理, 也會易寫很多很多, 於是便開始寫. 不過也是寫得很差, rotation 的部份不長但花了很多時間, 過 sample 後好像己經是 260 了 (寫+debug 了一個時間..), WA 後發現 1 點的 case handle 錯了, 改後竟然得到 TLE, 便努力 opt rotation 的部份, 繼續 TLE, 最終發現 rotation 的 index 有點問題, 改之, 此時剩下數分鐘, 雖然只是 training 沒有緊張的感覺, 但在 297 時 AC 也是很興奮的

Sunday 9 October 2011

POJ 1739 Tony's Tour

非常慘烈的AC..

題目是最最最基本的插頭 dp, 其實在隊中不是我負責的, 不過做做也無妨
由於只有 39 種狀態, 所以便不用 hash, 直接做
但是因為不用 hash, 所以不能用 4 進制做 bitwise, 每次我都要把狀態 decode/encode
寫好後便是無限 WA..

WA 到不行的時侯, 便上網找別人的 code, 再怒 gen test case fc 自己的 output
不過也找不到 bug, 很灰, 一度懷疑是 test data 有 > 8 的情況, 但放了飛彈又沒有
最後發現 decode 一個 invalid 的狀態時, 會 access stack[-ive], 但不知為甚麼這情況只在特定 test data 出現

現在是 5/8 個男人了..!

Friday 7 October 2011

Team Training 6/10/2011, 8/10/2011

Tehran 2010

A: 簡單 by whh
B: 麻煩題 by faifai
H: Graph by whh
- 我用了 SCC 做, 其實只搵 source SCC 可以寫得簡單點
G: by whh
E: 枚舉 by gg
- 發現 hint 是錯的..
C: game 題? by faifai
D: 煩膠 by gg
I: 頹sim by gg
- 水過的, gen 個全是 robot 的 map 輕鬆 TLE..

K: 可以用 DnC on tree + BIT 做, 不過很麻煩, 懷疑可以用動態樹


NWERC 2010

A: greedy by faifai
H: sim by whh
C: by faifai
E: count degree by gg
B: dp by faifai
F: lower bound flow by gg
- 本身無諗住咁早打.. 統粹唔想空置 machine
J: by gg
- 很簡單, 但大家也好像很遲才發現這題
G: by gg
- 用類似 stack 去做

Wednesday 5 October 2011

Sem 3 3/13: 315 Asg 1 之後..

終於做完315 asg1 (還有 4 份), 鬆一口氣
其實份 asg 很簡單, 不過由裝 gentoo, compile kernel 等等都是第一次, 所以花了很多時間在無謂的錯誤上
一開始以為功課是寫 kernel, 不過可能是 S 班的關係, 變成了這份 (其實我覺得寫 kernel 好像比較有趣)

asg1 要使 user 可以令一個 process 變成 invisible (ps, top, /proc 不顯示, 不能 kill)
開頭完全無從入手, 感覺明明 lecture 都聽得明但是一到 asg 就顯得很不足夠
即使知道是改 /fs/proc/base.c, 但 base.c 有 3000+ 行 code, 每個 function 也很'可疑' (每次試也要重新 compile+reboot, 很費時間)
不過做完的時侯其實也很有成功感的, 也發現這個 course 的好玩之處在於做 assignment, 做完後會對 OS 多很多認識

還有雖然不用part pro, 但 315 終於令我覺得朋友很重要呢

Wednesday 28 September 2011

Team Training 19/9/2011, 21/9/2011, 26/9/2011

South America 2008


F: 極頹 by whh (6)
C: 頹 by whh (17)
G: 頹 by gg (41)
A: shortest path by gg (69)
- 起點做一次, 終點做一次, 然後再起點做一次
K: ad hoc by gg (85 + 3WA)
- 只試 Sum 的 factor, 可以 check remainder, 我的做法是 simulate 走圈的 process
E: 日期題 by whh (91 + 3WA)
I: euler path by gg (162 + 2WA)
- 顏色為 vertex, 城市為 edge, check 能否成為 starting edge 首先要連著 odd degree vertex (如有), 和 remove 後會不會做成 edge disconnection
J: simulation by whh (199 + 2WA)
D: dp by gg (195 + 1TLE + 1WA)
- 一開始使用 O(N2 * K) 的 dp, 之後再做使用 2 個 dp array 可以降到 O(N2)

B: 數學題, 好像是做 factorizing by whh


Hangzhou 2010


H: 簡單題 by whh (17)
B: 二分 + 類似 TSP 的 dp by gg (67)
J: KMP + dp (94)
C: 唔知係咩題 by whh (114 + 1)
F: CG + convex hull by gg (130)
D: 五子棋(201 + 1)
- 做法是找+數 winning position

G: AP + LCA, 雖然上年聽 joe 講過, 但寫的時侯還是遇到很多問題, 最後做法是 tree node = BCC + AP

Seoul 2009


A: 簡單題 by whh (17)
F: 最遠點對, 但沒有看到題目中要來自不同正方形的限制, 水過的 by gg (71)
B: by whh (109 + 2)
D: maximum subsequence average by gg (141 + 7WA)
- 做法有很多, 二分/迭代/凸包, 一開始寫二分 WA, 應該是精度問題, 最後過的版本是迭代 + 沒有用 floating point
E: Josephus by whh (217)
H: disjoint set + BIT by gg (241 + 2WA)
C: greedy by faifai, implement by gg (273 + 7WA)
- 一開始覺得是簡單的 greedy, 但又想不到, 看明 faifai RE 的 code 後再寫
I: probability by whh, 題目 1999 又長 (284)

J: 竟然看漏了一重要部份, 之後可以輕鬆 dfs 解決, 處理同位置的點用了一個巧妙的方法, 把距離都是 d 的點加上距離為 2d 的限制

Monday 26 September 2011

Petrozavodsk Summer 2011. USU Contest

好像是俄羅斯 IOI camp 的比賽 (好似係), 據聞難度十分高
見在 URAL 上舉行, 忍不住去玩

開始後不久見到有人過 J
首先想到 f(n) 可寫成一堆連續數的 Fibonacci 次方
如果有 f(n) 的質因數分解 form, 可以輕易找到答案

算法1 - 把 1~n 分解, 把每個數的質數加進 primes[] 中, N * sqrt(N)
submit test case 5 便 TLE..

算法2 - precompute 1~n 的質數, 分解時只試質數
submit - 還是 TLE..

算法3 - 分解一個數時, 只試質數, 再加上如果剩下的數是質數便 break
加上這個優化後 (%mod 變成 -mod 那些應該是一定要的) 終於過了..

之後做 D
如果 n = a*a*b, 那麼 a3 ≤ n 或 b3 ≤ n
所以只要試 n1/3 以內的數


K - KMP + DP
狀態是 dp[i][j] = 前 i 個 character, prefix 為 j 可以 match 到多少次
但 '?' 轉移時有些麻煩, 因為不能 greedy 地 match 下一個, 我的做法是不斷走 fail 更新, 理論上好像會達到 N3, 不過還是過了

CodeForces Contest #88

A - 慢..

B - 不熟悉的 game 題, 一開始沒甚麼頭緒, 發現 mod 很小, 便想到 O(mod) 的做法

C - 見到是 graph theory 又放在 C, 便覺得一定要做到, 用了一個邊割分的做法
Find(S: set of vertex){
    x = S[0]
    P = {y : x->y & y in S}
    Q = {y : y->x & y in S}
    Search edges(w, z) : (w in P, z in Q)
    Find(P)
    Find(Q)
}

想完覺得很優美, 以為用 vector 會很慢, 便用 array 模擬一個個 list, 寫起上來有點麻煩和冗長, 後來見到有人用 vector 也過了..

後來發現另一個(較簡潔)的做法: 先找任意一個 cycle, 之後可以簡單地找到 triangle

Friday 23 September 2011

CUHK CS Sem 3

好像很久沒打blog, 不知不覺原來己經開學 3 星期
生活主要也是圍繞在讀書和 ACM, 目前最想的便是去 exchange 和 WF, 己經報了 IELTS,

今個 sem 一共 take 了 5 個 course, 比大部份 yr2 CSers 少, 希望可以多一點睡眠時間和做題目吧

CSC313: 最喜歡的 course, 感覺就像去年 211 (更強烈), 會有種振撼的感覺. 經過 intern 和幾堂 lecture, 發現自己還是對理論的興趣比較大..
CSC315: 由於對 OS 沒有認識, 所以可以說會學到很多新東西. 不過興趣不大, 只希望快快搞掂 assignment
CSC316: 由於前面的 topics 都有一定的認識, 加上九半的關係目前還沒有上過堂, 不過看免費的 textbook 也很好, 去到後期應該會去上堂吧
CSC317: 沒特別感覺的一個 course, 感覺有點頹, 不知為甚麼到現在還沒有 quiz
CSC323: 上堂完全不知道學到甚麼, 目前除了那個 project 好像頗有趣外其它東西都是莫明奇妙的

其實打 blog 的動機是因為今天的 training 太興奮
今天主要是立志講 graph, 他列出的問題有一半都是沒有看過的, 大開眼界
例如 odd length shortest path, 總覺得應該是很經典會看過但就是沒有看過
心裏有一種很強烈想知道怎麼解的想法

還有 bipartite graph edge coloring, 雖然最後的做法不難, 但是能一步步 prove 出來都是很興奮的, 特別是又用回 211 的東西.. 原來看一個 proof 和自己想一個 proof 的感覺是差很遠的
有時對一些明明很理性的事物會有很感性的感覺, 很奇妙

Saturday 3 September 2011

URAL 1580 - Dean's Debts

首先 N 個 unknowns 至少要有 N 條 equations
多過 N 條的話只保留 linear independent 的
之後便聯想到一個 |V| = |E| 的 Graph, 即頂環樹

有一個頂環樹, 一定是從環的部份開始解
但是不是每種環都有唯一解, 要 odd cycle 才可以 (用 determinant 可以證明)
所以每個 connected component 要至少有一個 odd cycle 才有機會有唯一解

環的解可以綫性計算, 然後順著邊計算 tree node 的解
之後多餘的 edge 只要 check 是否 consistent 便可以

總時間 O(N+M)

Thursday 1 September 2011

上海MS Intern 遊玩一覽

六月
8: 人民廣場, 東川路晚飯
11: 徐家匯, 豫園
12: 科技館, 明珠塔
18: 人民廣場, 小肥羊
19: 吳徑, 交大
25: 余山
26: 單車

七月
2: 單車
3: 交大, 江川東路
9: 蘇州
10: 歐尚
15: 徐家匯豆撈
16-17: 無錫
23: 蘇州
24: IOI Day 1
30: 美術館, 人民廣場
31: 單車

八月
6-7: 黃山
13: 數碼港上海一日遊
14: 閔行公園
20: 七寶
21: 朱家角
27: 自然博物館, 靜安寺
28: 動物園, 上海體育館

上海MS Intern VII

晚上就要走了, 雖然沒有想家的感覺, 但總有點期待三個月離開香港再回去的那種感覺
但相對地不捨的感覺更多, 在這裏認識的人, 以後可能不會再見

第一次在外地生活這麼長時間, 回到香港說不定還要適應一下
再見閔行, 再見上海

Wednesday 31 August 2011

SRM 516

悲劇呀..

250 很快便想到算法, 但寫了很久
500 看了兩次題目才明, 發現是很簡單的 greedy, 寫的速度還不錯
1000 由於 500 偏淺, 所以很有信心地把餘下的時間花在 1000, 交了個不覺得正確的解..

challenge phase, 1000 很快被 petr cha 了, 然後 petr 很強勢的從 rating 低至高逐個 cha 掉他們的 500..

之後便上不到網, 於是去睡覺

第二朝一早醒來, 上 profile 發現 rating 大跌, 心知不妙
入去看看, 發現 250 忘了 -'0', 500 greedy sort 的 < 寫成 > 了..

Sunday 28 August 2011

上海MS Intern VI

暑假駛入尾聲, 亦代表 intern 快要完結
下星期就要 final presentation 了, 不過現在還未整好 PowerPoint
總覺得之後會掛住 office, 雖然我也不知道為甚麼會有這種想法

繼無錫而後, 又去了蘇州, 黃山, 朱家角
本來想打遊記的不過因為太懶所以沒有打
上海市內則去了自然博物館, 美術館, 七寶, 還有數碼港安排的豪華一日遊
好像除了杭州以外, 應該要去的地方都去了

看了幾集 Star Trek 又覺得不及第一次看的好看, 於是便沒有看下去了
近排開始打機: 大航海時代4, 電車GO!
不過這個月晚上很多天都出去食晚飯, 回到酒店已經夜深

今天應該是這次 intern 最後一次到市區, 去了自然博物館, 行行了 N 次的南京路步行街
之後沿著南京西路到靜安寺
感覺上開始認得路了

還有數天就回香港, 其實我也沒有想家
在這裏住了快 3 個月總覺得有些不捨, 不過總覺得這想法很奇怪..

Tuesday 23 August 2011

SRM 515

250
一開始看錯了以為可以 rotate 任何角度, 到發現只能轉 30k 度時已經跌了>20分
最後 submit 時只剩下 18x

550
在 250 緩慢的情況下, 如果最後只做到 250 的話 ranking 一定很低
由於 550 估計只有大約 30% 機會做到, 所以開了 1000

1000
發現是 graph 題, 覺得有機會做到
做法是枚舉 F 和 R 的位置, 計算每一格到 F 和 R 的距離總和
然後再做一次 Dijkstra

結果 1000 過了, division 排第 6, 升了紅色
不過做到 1000 真的十分偶然, 首先題型要是自己擅長, 想到題解又要 code+debug 到
所以要長期保持紅色不能只靠這些偶然, 還是要穩定地做到 500

Monday 15 August 2011

URAL 1833 - Hopes of Rowing

題目可轉化為一堆 bonus[ai] + bonus[bi] ≥ k 的不等式
By 直覺, 一定存在一 optimal solution 其中 bonus[i] 為 k/2 的倍數 (0, k/2, k)
(其實好像可以 prove, 不過我不懂)

先假設上面的前題正確, 但是三種可能性很難處理, 所以先統一所有 bonus 都是 k/2, 那樣就只剩下兩種可能性
再轉化為 (其實這 step 不是這樣想出來的, 而是由 solution 推導出來):

bonus1[ai] + bonus2[bi] ≥ k/2
bonus1[bi] + bonus2[ai] ≥ k/2

其中 bonus1[i] 和 bonus2[i] 都是 0 或 k/2

把 (bonus1[ai], bonus2[bi]) 視為一條 edge, 會得到一 bipartite graph, 而且要做的其實就是 minimum vertex cover!

由 König's theorem 可知, 對於 bipartite graph, minimum vertex cover = maximum matching
所以之後只要做 matching 再找出 cut 便大功告成

Friday 29 July 2011

IOI 2011

今年 IOI 的 problem set 非常好, 難度適中又可以 split 開 top 的 contestant
在此打下題目的 brief solution, 其中 Elephant 是參巧 FHQ 的做法的

Updated - Elephant official solution
先把 N 隻大象分成 K 個區間, 每個區間儲著 N/K 隻大象
假設某區間有 p 隻大象 (0, 1, 2, .. p-1), 要儲存:
pos[i]: 大象 i 的位置
opt[i]: 對於這區間, cover 大象 {i, i+1, .., p-1} 最少用多少 camera
max[i]: 在 cover {i, i+1, .., p-1} 時, 最右的 camera cover 到最右的位置

有了這些 information, 可以在 O(K lg N) 搵到最少所需 camera, 做法是由最左的大象開始, 根據 max[i] 移動, 並 binary search 在下一個 (可以跳過幾個區間) 區間的位置, 再移動
每次 query 都要做, 總時間 O(MK lg N)

每次 update 最多只會影響 2 個區間, 可以用 binary search 找出是哪個區間
只要把受影響區間 O(N/K) recompute 就可以
方法是由右至左 construct, 總時間 O(M * (lg N + N/K))

但是, 區間的大象數目可能會變得不平均, 所以當一區間的大象數目跌至 0升至 2N/K 就要把所有大象重新分區間
在整個 process 中最多只會重組 MK/N 次, 所以整個複雜度是 O(MK/N * N) = O(MK)

可以解得當 K = sqrt(N) 時達至最小值, 所以整個算法複雜度為 O(M * sqrt(N) * lg N)



Garden
用 edge 作為狀態, 建立一新 Graph. 由於行完每條 edge 後行下一條 edge 是固定的, 所以新 Graph 中的每一 vertex 都有一條 outgoing edge, 形成頂環樹
對於每一個 query, 計算每一個 node 對應的 start edge 走 G[i] 步後會到達哪條 edge, 一共是 O(M)
整個算法為 O(MQ)


Race
POJ 1741 頗相似, 做法是 Divide and Conquer on Tree
每次選 Center of Tree 作為 root, 用 O(N) 計算它所有 children 的距離和高度, 然後 O(N lg N) 考慮所有經過 root 的 path
Recursive 地計算它的 subtree, O(N lg N lg N)


Ricehub
首先注意到其中一個 center 一定是 hub 選址的其中一個 optimal solution
對於每一個 center, binary search 它可以 cover 的距離 (左右相同) 或 binary search 可以 cover 的 center 的數目

注意: 如果由左到右 sweep line 好像會有問題, 因為 left bound 並不是 monotonic increasing 的


Crocodile
由 exits 作為起點做 Dijkstra, 當一個 vertex 被第 2 條 edge reach 時才算是 visit 該 vertex


Parrots
81分做法: 原本的 array 可以看成一條長度為 8N 的 01 string, 只要傳送 1 的位置就可以
>81分: k 最小可以是多少? 其實傳送 kN 個 [0, 255] 的整數可以產生的可能性為 H(256, kN) = C(255+kN, 255)
Solve C(255+kN, 255) ≥ 255N 可以解 k 約是 4.09 (N = 64)

這題的重點就是怎樣可以在有限時間, 空間內做 mapping.
我目前想到最好的方法是, 2 個數字為一組, 用 8 個數字, 傳送 14 次 (k = 7), 可以預先把所有可能性打表 ( H(8, 14) 個可能性 ), 就可以 efficient 做 mapping


Elephant
首先把問題變成一棵 Tree, 每一個 node 代表一個 position, 定義:
黑點: 每隻大象的位置都是一黑點, 它的 parent 為 position + L 的 node
白點: 它的 parent 為右面或同一位置中最近的 node
Root: 在 +INF 的地方

答案就是最左的 node 到 root 的 path 上黑點的數目
每一個 move 都可以拆分為 insert 和 delete

Delete(黑點): 把該 node 變成白點 (需要改 parent)
Insert(黑點): 在 position + L 建立一點白點, 作為它的 parent
Insert(白點): 把 parent 連到在它右面或同一位置最近的點, 黑點優先

注意: 一個 position 可以多於一點, 要避免白點形成 cycle

Implement 用到 2 個 data structure: 動態樹 (dynamic tree / link-cut tree) 和 Binary Search Tree

Sunday 24 July 2011

上海MS Intern V

無錫一日遊
第一次 5 個香港 intern 一起去玩, 選了個不遠而大家也沒去過的地方



早上七點出發, 九點抵達上海火車站, 買票比想像中複雜



高鐵, 買票的時侯要回鄉証, 幸好大家都帶了
買了企位 (其實是不是會搞到超載的..)



到達無錫, 經過多方洽談, 決定跟一些旅行社交易 (它提供交通和景點門票, 比正價平一點, 應該是從景點那裏抽佣)
一開始 whh, helic, tong 和我都很不行, 不過最後還是付了錢



三國城 - 為拍電影/電視劇而建的 (好似係)


坐船遊太湖, 架船下層冷氣的散熱口對正上層甲板, 咩設計來的 (o:


「水軍訓練營」- 途中 helic 跌左副眼鏡落去, 花左一番功夫先搵返


唔知做緊咩既演出



之後過隔離 - 水滸城, 其實都係差唔多



買了弓箭玩具



大家係度瘋狂買野(又幾抵), 最搞笑係入面檔檔賣既一樣 (o:


$5 騎馬影相



$10 玩射箭


根據計劃, 本來是去甚麼古鎮的, 不過被黑的司機說服了我們去甚麼動物園




動物園夜場 - 其實我地入去玩機動遊戲的
右圖的機動遊戲堅正
表演 - 無劇情可言, 不過有些 tricks 係第一次見


走既時侯大雨到hihi, 最後差唔多 11pm 先返到火車站, 發現無哂車
討論好唔好 book 間房過一晚, 最後決定搭 3am 的車回上海
找到間 24hr 麥當奴 hea, 玩超用腦 game & Italian





呢架火車由成都開來, 已經行左 30hr, 所以上到車成地垃圾



這算是中國「真正」的火車吧, 老老實實, 企個半鐘已經差示多是我的接受極限



回到上海, 搵左間中式快餐店食早餐




統計支出


項目 支出(RMB)
教師之家->上海火車站 7
早餐 10
高鐵 60
無錫火車站->三國城 2
三國城+水滸城+太湖遊船 120
7-up 4
午餐 19
木弓玩具 10
果粒橙 5
射箭 10
水滸城->動物園 15
動物園夜場 65
雨衣(share) 1
晚餐 36
動物園->無錫火車站 1.2
支裝紅茶 5
麥當奴(share) 4.8
K車 (無錫->上海) 20
早餐 10
上海火車站->教師之家 7

一共用了 412 RMB

Tuesday 12 July 2011

上海MS Intern IV


先簡單說說工作: 在 team 上主要是做一些輔助的 tools, 差不多做好一個 project 了, 聽說做完後要 present 呢

近來都是星期六玩一整天, 然後星期日則睡到下午, 在黃昏踩單車去不同的餐館吃飯 (其實是因為來上海後每星期六晚上都有比賽, 所以都很遲睡)
上星期六跟團去了蘇州, 不過印象不是很深刻, 始終比較喜歡自己 plan 行程而不是跟團

然後就講下晚上娛樂啦

遊戲
其實Braid不是來上海才玩的, 不過也一拼記下吧
Braid: 和時間有關的遊戲, 破關的難度不亞於做題目! 故事很深奧, search 了幾個網站才明白, 絕對稱得上經典
World of Goo: 物理遊戲, 有點像起橋, 但很多變化, 也當是解謎遊戲, 另外 soundtrack 很好聽


由於不遠的交大有間書店, 又有85折, 於是養成定期去買書的習慣, 目前在看東野圭吾的書
時生: 和 Back to the future 差不多, 沒甚麼驚喜
殺人之門: 不錯
單恋: 很喜歡故事的發展速度

不過其實成篇 blog 既重點, 就係我開始睇 Star Trek !
其實是在看 The Big Bang Theory 時, 入面的角式都很迷 Star Trek, 於是便看看, 發現真的很好看
上 wiki 一看, 發現有 11 集電影, 七月底前看得完嗎?

Sunday 3 July 2011

上海MS Intern III


單車大冒險!

由教師之家出發, 沿著龍吳路, 踩到徐匯區吃午飯
然後轉向東面, 在陸家浜一帶乘渡輪到對岸

過了岸便是在拆卸的世博, 發現演藝中心館變成了一個商場的地方
途中經過一間一年前吃過的餐廳, 感覺很特別, 一年前這裏還是十分熱鬧的地方, 現在變得很冷清

轉向東北, 踩到世紀公園, 發現好像要錢 (上海很多公園都要錢的) 和好像快關門, 便到科學館附近吃晚飯
最後沿著和原路差不多回教師之家

粗略估計今天踩了>7 小時, 主要問題唔係攰, 而係個單車坐位會令到屎忽好痛
同埋這裏的天文台預測今天陰天, 但結果是, 「說好的雲呢?」

晚上 SRM, 又做不到 500 了 (連續幾次做不到了..), 不過 250 危機四伏, 順利地 cha 掉 3 個
第一次覺得 challenging phase 太短 :p

Wednesday 29 June 2011

上海MS Intern II


開始intern以來主要都是改改別人的code, 這幾天終於要寫新的東西 (雖然都是加在以有的東西)
其實時間主要都不是花在打code上, 而是無限google一些自己不懂的東西, 有時會想如果那些 function, system 一早識的話, 我基本上可以 1 日做完佢 assign 我 1 星期做的 task, 不過佢應該是預左時間我用來學習的吧

另外, 終於買了單車 (其實也是二手的, 不過睇落幾新), 又可以遲點起床:p
順帶一提, hea 踩單車返工和 whh 跑的時間差不多

看完 TBBT 後, 又看了兩本書+電視劇 (因為夜晚其實無咩做..)
內含劇透

流星之絆

其實一直也沒把它當成推理小說, 也沒有猜兇手是誰之類, 我比較喜歡一邊看一邊享受劇情
看完小說後發現還有電視劇, 便一拼睇埋, 不過我對電視劇的評價偏低, 原因:

1. 感動位/搞笑位太多, 主角成日有講有笑, 完全沒有那種復仇的感覺, 不夠黑暗
2. 主角搵明星做, 完全唔 match 書入面既人
3. 最後栢原竟然沒有自殺! 最後仲要整個 happy ending, 迎合市場

總結來說, 除非是很得閒想 fing 時間, 否則都是不要看電視劇


隔離島

由於 faifai 又要睇又要驚, 令我很有興趣
結局不算 surprising, 至少佢唔係第一個故事係咁, 不過並不影響整個故事的可觀性

又發現原來有電影, 準備看, 在 IMDB 上有 8.0 的, 看來拍得不錯

Thursday 23 June 2011

CodeForces Contest #75

近來幾次 Codeforces 都出現 D 和 E 一樣分數的情況, 其實是對我有利的, 因為有機會懂得做的題目多了 -> 做到 D 或 E 的機會大了

E - 有 N 個 igloo, 在時間 = t 時, 第 i 個 igloo 的高度為 ai + bi * t . Queiries: 在時間 = t 時, output 第 x 個至第 y 個中最高的那個

看完題目, 最先想到的是:
1. 90% 可以用 segment tree
2. 可以把 queiries 按 ti sort 好
3. 高度那 part 想起 Best Plan[1]

由於想要知道 [x..y] 中最高的那個, 因此 segment tree 上的每個 node 都儲著一條 queue, queue front 就是當前最高的那個 igloo
現在目標是對 [x..y] 中, 找出 sequence S, 使得一開始 S1 最高, 過一段時間後變成 S2, 如此類推

一開始我按 b[i] 由小至大排, 再 remove 那些 ai 比後面小的, 之後每次 query 只要睇下使唔使 pop queue front 便成, 不過過不到 pretest
之後發現假如有 3 個 igloo A, B, C, 會有機會出現以下情況:

(A > B > C) -> (C > A > B) -> (C > B > A)

即是, 在 B 超前 A 之前, C 已經超前 B
解法方法: 像做斜率優化 dp [2] 那樣, 要計算超前時間, 即是對於 A, B, C , 在 push C 入去時, 除了 check 是否好過 B, 也要 check 超前時間, 即 Cross(C, B) > Cross(B, A)




C - 一個 Graph, 每次 add 一條 edge, 問有多少種方法選取 edge set S, 使得 S 能拆分為數個 edge disjoint cycles

很多人做到 (雖然聽說和某 TC 題目相近 [3]), 不過又想不到怎樣做, 看完題解覺得很有趣

做法: 每次 add edge 時, check 條 edge 的兩端是否已經 connect (用 disjoint set), 如果是, 則把答案 x 2

不過最精彩的還是證明, 大約是這樣的:


把每一條 edge 寫成一支 1 x N 的 vector, 連接的點 = 1, 否則 = 0
例如 N = 5, 則把 edge (2, 5) 寫成 <0, 1, 0, 0, 1>

[Propeties] 如果有一 set vector 把它們 XOR 起來的結果是 0, 則乎合選取方法, 反之亦然
[Proof] 把它們 XOR 起來為 0 <==> 每個 node 的 degree 為偶數 <==> 存在 euler cycles

問題變為, 現在我們有一 set vector S, 有多少種選取 S 的 subset 方法使得 XOR 起來 = 0 ?
答案是 2|S| - rank(S)

解釋: 先任意找出 S 的 basis, 對於不是在 basis 中的 vector, 可以任意選取 (2|S| - rank(S) 種方法), 然後有 exactly 1 種方法在 basis 中選一些 edge 去補上乎合條件

所以, 每次 add 一條 edge, 只需看它的 vector 是不是和 S linear independent, 可以證明, 如果這 vector 和 S 是 linear dependent <==> 這條 edge 的兩端已經 connect



References:
[1] HKOI 2007 Junior
[2] http://www.topcoder.com/stat?c=problem_statement&pm=6779&rd=10002&rm=249950&cr=13358640
[3] POJ 3709

Official solution: http://www.codeforces.com/blog/entry/2179

Saturday 18 June 2011

上海MS Intern I


來了上海一個半星期, 工作了 6 天, 開始知道大約在做些甚麼
工作主要是寫 C#, 其實和 Java 十分相似, 目前覺得學過 Java 和 SQL 在工作上十分有用
不過其實有咩問題都係問 mentor, 很方便:D

目前週末都會到市區, 由住所到人民廣場站也要差不多 90mins, 另外上海的科技館挺有趣的
不過一出市區價錢就是香港價了
計劃過了雨季 (六月) 就試試離開上海去其它地方玩

過去一週每天晚上都在看 The Big Bang Theory
由於在搜狐上中國地區(不包括香港)是授權播放, 所以大部份時間都沒有連 vpn
不過由於實在是太好看, 所以忍不住要宣傳一下

主題曲:



Our whole universe was in a hot dense state,
Then nearly fourteen billion years ago expansion started. Wait...
The Earth began to cool,
The autotrophs began to drool,
Neanderthals developed tools,
We built a wall (we built the pyramids),
Math, science, history, unravelling the mysteries,
That all started with the big bang!

"Since the dawn of man" is really not that long,
As every galaxy was formed in less time than it takes to sing this song.
A fraction of a second and the elements were made.
The bipeds stood up straight,
The dinosaurs all met their fate,
They tried to leap but they were late
And they all died (they froze their asses off)
The oceans and pangea
See ya, wouldn't wanna be ya
Set in motion by the same big bang!

It all started with the big BANG!

It's expanding ever outward but one day
It will cause the stars to go the other way,
Collapsing ever inward, we won't be here, it wont be heard
Our best and brightest figure that it'll make an even bigger bang!

Australopithecus would really have been sick of us
Debating out while here they're catching deer (we're catching viruses)
Religion or astronomy, Encarta, Deuteronomy
It all started with the big bang!

Music and mythology, Einstein and astrology
It all started with the big bang!
It all started with the big BANG!

Sunday 5 June 2011

GCJ 2011 Round 2

Rank 6xx, 徹底地輸了
A - 一開始不斷把 velocity 和 displacement 調轉.. 大約 20 mins 完成
B - 算法很直觀, 但 debug 了很久, 用了 50 mins
C - 一開始以為最小和最大分別是 1 → n 和 n → 1, Incorrect 後寫了個暴試把 n=10 以內的都試過, 在繼續以這假設正確的前提下又找不到 bug, 就放棄了
D - BFS → DAG → DP. 但一直在 Incorrect. 找到 N 個 bug 後也是過不到. 完場

最後也有 T-shirt 但不能晉級. 後來搞了很久也過不到 D, 發現有個致命漏洞, 但又想不到怎樣改. 剛才才想到個 state 係 [previous][current], 咁樣先可以唔重覆地數 Thereat node..

Thursday 2 June 2011

POJ 3709 K-Anonymous Sequence


斜率優化DP

重要的observation
1. If k->i is better than j->i and k > j, then for all r >= i, k->r is better than j->r
2. For all j < k, there exists i such that for all r >= i, k->r is better than j->r *

然後做 DP 時, maintain 住一條 queue, 乎合以下條件

1. 在當前的 i, q[x] 比 q[x+1] 好
2. q[y] 比 q[y-1] 好的時間 大於 q[y-1] 比 q[y-2] 好的時間

每次取計算 DP 值時, 先用條件(1) pop 走 queue 頭
再用條件(2) pop 走 queue 尾, 再把 i-m+1 push 進 queue 尾


* 有時 i 會是 +inf 或 -inf, 可以 handle 做 0 或者 n+1 咁

Monday 23 May 2011

Yandex 2011 Round 2

好不容易才打到 Round 2, 不過都係與 T-shirt 無緣

A - 見識過 Round 1 的 A, 對這次的 A 已有心理準備, 先寫一個慢的 program 去找 observation, 有 2 個重要的發現:

4, 49, 499, 4999, 49999.. 是 peak 值 ;
去除這些 peak 值, 如果 x < y, 有 weight(x) < weight(y)

所以解法是先試試 weight(r), 然後試試 4, 49, 499 .. 等


B - 題目個 tag: Constructive algorithm
一開始還是被嚇住了, 之後想到一個很麻煩的做法:

1. 對每個 row, 每堆連續的 space 可以用 length 2 和 3 的 figure cover (2+2+2... / 3+2+2+2...)
2. 之後就是 handle 一些 alone space, 我先把垂直相連還未被 cover 的 space 用上述方法 cover
3. 最後便是一些

#000#
##.##
11122

的 space, 如果上下都是 #, 則無解; 否則可以「痴」到上下的 figure, 但還有一個麻煩情況, 就是


#.#.#
#...#
#.#.#

不合法的 figure. 所以如果上下的是 "000" 的形狀, 我會把它們砌成:


#.###      #0###
#111#  ->  #011#
#.###      #0###

怎看也很煩膠的方法, 用了 >30 分鐘去寫+debug, 不過最後還是過不了, 原因是我 label 那些 figure 時應該出了錯, 用了同一個數字去 represent 算法「認為」不是同一個 figure 但相連的 figure, 其實我寫的時侯已經有刻意留意, 不過問題是只有 10 個數字用, 十分不足, 逼不得已去「重用」一些數字時出錯..


C - 又是 AC 自動機 + DP, 完場前 5 分鐘寫完, 不過連 sample 也未過到; 之後都用左好多時間 debug, quote Joe神一句

因為曾經做過的關係,有些第一次做會錯的地方都避免了

原來第一次做真的會有很多地方出錯, 而且是對著錯的 data 才發現錯處, 即是就算放棄 B 不做也應該過不到 C, 而且過到 B 也入不到頭 70, 結論就是無論如何也入不到頭 70

Wednesday 18 May 2011

SRM 504.5

250
又是和 4,7 有關的數論題
想過用BFS, 但想想又覺得會寫得很長
最後還是直接把 10 個 case 打落去

550
花了一段時間, 觀察到 money[] 會續漸趨向一樣, 然後就可以很快計算結果
但想來想去也覺得就咁 simulate 趨向一樣前的 process 會很慢..
加上不懂得在不 overflow 的情況下計算 average (是出題者刻意的伏?), 所以決定開 900 做

900
其實是頗 standard 的機率題..
我的做法是計算 p(x) = 前面有 x 個人, 後面沒有人時, 被選中的機率
可以在 O(N2) 計算..
但是完場時還是過不到sample, 後來發現沒有 handle 「只剩自己一人」的case

Monday 18 April 2011

All-Ukrainian School Olympiad in Informatics 2011

ACM style, 以下是我做題的順序

E. Points

利用

可以快速計算, O(N) 時間, O(1) 空間

D. Plus and xor

考慮 B 的每一個 bit (由 MSB 到 LSB), 如果是 1, 則 X 和 Y 的那一個 bit 必定有一個是 1 另一個是 0, 那當然把 1 assign 給 X
如果 B 的那個 bit 是 0, 則計算如果 X 和 Y 的那一 bit 均為 0 的話 X+Y 是否能 ≥ A

留意
if (X + Y > A)
會 overflow

A. Gift

一開始以為對 gold 做 ternary search 可行, 但 WA 後便發現很容易作出反例..
之後想想有甚麼必定正確的做法:

首先 sort gold, silver 的可能值
然後用 2 支 pointer, 一支在 gold 的最前, 另一支在 silver 的最尾, 做 sliding
但是由於每次 check connectivity 要 O(E), 整個 algorithm 是 O(E2)

後來想到了 http://poj.org/problem?id=2838, 也就是 maintain 著一棵 tree, 而不是一個 graph
簡單來說, 每次 insert 一條 edge 時, 如果形成環的話, 可以 delete 環上的一條 edge 而不影響連通性
在這條題目中, delete 的便是 silver 最大的那條 edge 了

由於邊的數目最多為 V-1, 每次 check connectivity 只要 O(V), 於是 total time = O(VE)

B. Mice

這條理論上比 A 簡單
首先把只有一個選擇的 mice 所選的 cheese mark 上時間截
然後對於剩下的 mice, 可以 greedy 的決定去左邊還是右邊

F. Tourist

看到這類題目通常都是先把 equation 寫出來, 例如去完 event i 後能去 event j 的話, 必需滿足

Ti ≥ Tj + Xj - Xi (假設 Xj ≥ Xi)

然後移項, i 歸 i, j 歸 j

Ti + Xi ≥ Tj + Xj

然後, 可以證明到, 只要滿足 (1) 和 (2),
Ti + Xi ≥ Tj + Xj    (1)
Ti - Xi ≥ Tj - Xj    (2)

是去完 event i 後能去 event j 的充份條件
之後, 便可把問題轉化為在 2D plane 上找最長不下降線段

Sunday 10 April 2011

COCI 2010/2011 Contest 7

Q4 是給一個 N x N map, 每一格有高度
現在由起點出發, 經過所有 checkpoint(s) 並回到起點。目標是最小化沿途中 最高點 與 最低點 之差
N ≤ 50

雖然是 path, 但其實不用真的找條 "path" 出來, 只要想成找一棵 spanning tree
先枚舉 path 上允許的最低點, O(N2)
然後二分 path 上允許的最高點, O(lg N)
做 flood fill 檢查可行性, O(N2)


Q5 given 一個有向圖, 每個頂點的 out degree 不大於 1
然後有 Q 個操作, 每次可以
remove(x): 移除 x 的 outgoing edge
query(x): 問由 x 開始走, 最終會到達邊個 vertex, 如果是 cycle 就 report 有 cycle


看下去十分像 disjoint set, 但 disjoint set 不支援 delete, 不過支援就是 dynamic tree 了
個 trick 就是可以倒著做, 那 delete 就變成了 union
所以先把所有 operation 讀入, delete 的照 delete
然後以 operation 倒序 process, 就變成一般的 disjoint set 了

Monday 4 April 2011

CodeForces Contest #70 D

題目要求 maintain 一 set 點的 convex hull, 有 2 種 operation:
1. add(x): 把 x 加進 S 中
2. query(x): 問 x 是否在 S 的 convex hull 內



如果一點在 convex hull中, 以後都會在 convex hull中
具題做法是, 先找一點 convex hull 內的點 (我用的是最初 3 點的 CG), 以該點為 pivot point P

然後用一個 set 去 store 住 convex hull 上的點, key 是與 P 的 polar angle
對於新的點 x, 先找 x 在 S 中的左右兩點, 用 cross product 便可判斷是否在 convex hull 中

如果要把 x 加進 S 中, 先判斷 x 是否在 convex hull中, 如果不是, 只要對 x 左面和右面不斷 erase 形成反角的點 ; 否則 convex hull 不會改變



容易錯的地方
1. 兩點一樣的點 (以為題目說 input 沒有 2 點重覆, 原來只是保證 convex hull 沒有)
2. polar angle 相同
3. 和上面兩點有關, 就是在 set 中 insert(x), 但原來 x 已經存在, 之後 erase(x) 會把原本的點都刪埋
4. add(x) 前沒有 check x 是否在 convex hull 中

Thursday 24 March 2011

URAL 1691 - Algorithm Complexity

題目:
給出一個有向圖, 設 F(N) 為由 S->T 長度為 N 的 walk 的數目, 問是否存在一非負整數 k 和常數 C 使得 F(N) <= CNk
Input: Graph, S, T
Output: k 的最小可能值


題解:
題目十分technical, 其實是說 S->T 的 walk 的數目是否能寫成 N 的多項式 (有點像big-O 的定義), 即 F(N) = O(Nk)
仔細想, 如果不能的話其實就是指數式, 即 F(N) = O(cN)

在甚麼情況下會變成exponential呢? 首先想到的是如果每步都有多於1種選擇, 咁就變左ck, 如 sample 2
然後又想甚麼情況才是N2, N3 等, 就會發現就是把 N 步「分配」到不同的環中, 即 C(N,M) = O(NM)

所以, 先對圖做SCC
每個SCC可以分為數類:
1. 只有一個node
2. 一個簡單cycle
3. 以上皆否

明顯地, 如果S->T 能路過 type 3 的SCC, F(N) 就即刻變左 exponential
剩下的, 便是在縮點後的DAG中找 S->T 路過最多 type 2 的 path, 做 memorization dp 即可

怎樣判斷是type 2 還是 type 3 呢? 只要在該SCC中比較一下 |V| 和 |E|

還有URAL的stack size很細, 100000 個 node 做一次 dfs 都 stack overflow
解決方法: 我將由 1->n 改為 n->1 就過了..

Sunday 20 March 2011

小記

近幾次的 CF 的 SRM 都打得很差..

Friday 18 March 2011

URAL 1676 - Mortal Kombat

Problem
Given a N x M bipartite graph, determine which edges can be selected in a perfect matching.

Solution
First, find an arbitrary matching. If an edge is selected in the matching OR contains in any augmenting cycle, output that edge.

To determine whether an edge is in an augmenting cycle, find the SCC in the residual graph. See whether both ends of an edge is in the same SCC.

Trick: N may not equals M. My solution to this is add a dummy node in the left side.

Sunday 13 March 2011

POJ 2986 - A Triangle and a Circle

要搵一個三角形的一個圓形 intersection 的面積

做法: 對於三角形ABC 和圓C, union的面積 = [ABO ∩ C] + [BCO ∩ C] + [CAO ∩ C] (signed area)
而每一次計圓心三角形的 intersection 可分為4個case

另外, 使用 asin 和 acos 時, 應該 handle asin(1.00000..001) 的情況

Friday 4 March 2011

URAL 1699 - Turning Turtles

Problem
Given a W x H map where the passable cells form a tree. Q queries: what is the number of turns required travelling from cell (x1, y1) to (x2, y2)?

W x H ≤ 100000
Q ≤ 50000

Solution
Obviously it is a LCA problem. However, the problem is the weight of edges depend on 3 nodes (not 2). Assign weight[u][v] =

1 if parent[u], u, v is a turn
0 else

For Query(x,y), find z = LCA(x, y). Then find 2 children of z, x' and y', such that the path is x->x'->z->y'->y. The answer is sum[x]-sum[x']+sum[y]-sum[y']+IsTurn(x',z,y'). Special handle the case x or y = z.

I implemented a dfs to pre-process the tree for LCA queries. However it will cause stack overflow. Therefore I implemented a non recursive version tree traversal, using stacks. So complicated..

Friday 25 February 2011

URAL 1770 - The Party of Ural Champions

A useful observation: The original graph can be obtained from removing some edges from the given distance matrix. Futuermore, if d[i][k]+d[k][j] = d[i][j], then edge (i → j) may be removed.

My solution used Reversed Floyd-Warshall algorithm. The basic idea is like

for k=1 to n
  for i=1 to n
    for j=1 to n
      if d[i][k]+d[k][j]==d[i][j] then d[i][j]=INF

However, the problem do not allow directional edge, so we need to avoid setting d[i][j]=INF but keeping the edge (j → i). To solve this problem, I used the following method:

for k=1 to n
  for i=1 to n
    for j=1 to n
      if d[i][k]+d[k][j]==d[i][j] AND r[j][i] then d[i][j]=d[j][i]=INF
      else if d[i][k]+d[k][j]==d[i][j] then r[i][j]=1

At last, don't forget to see if the input matrix satisfy triangular inequality

Monday 14 February 2011

Addiction

Problem statement

There are N addictions each has a strength Si. At each week, you can remove one addiction and restore any number of addictions that you have removed. The only constrain is the change of total strength of addictions you currently have must falls into the range [-D, 0]. Find the maximum number of addictions that you can remove, and minimize the number of weeks to achieve this.

1 ≤ N ≤ 1000
1 ≤ Si ≤ 10000

Solution
First, there is an interesting property that if an addiction can be removed, any addiction with less strength can be removed also.

Although this seem intuitive but we should prove it anyway. We prove it by induction.

Assume that we can remove some addiction with strength P. Consider an addiction with strength T (T < P). Let the set S be the set of addiction with strength smaller than T and Sum(S) be the sum of strength in S. If T-D <= Sum(S) <= T, then we are done. Else, we have Sum(S) > T. Consider the addiction with smallest strength Q in S, if Q is smaller or equal than D, then we remove it from S directly. Else, there must exist some combinations of addictions with strength smaller than Q with sum of strength in [Q-D,Q]. Then we can remove that addiction with strength Q and replace it with that combination. As a result, Sum(S) decrease not more that D in each step and it will fall into [T-D,T] eventually.

Actually this fact is not necessary for our solution, but it is beautiful :P.
The solution is simple - Dynamic Programming.

Sort the addiction by strength first. Assume F(i) be the minimum number of weeks to remove addiction i. We have

F(i) = F(x1) + F(x2) + ... + F(xm)

where Sx1 + Sx2 + ... + Sxm is in the range [Si-D, Si].

And we can do this by a knapsack.
The total time complexity is O(N * max(S))

Bridge hand

搭Airbus回家時, 用iphone玩的一手牌, 只係我覺得打得好開心:D
我是south, 但個 game 設定係只要我方叫到合約, 都係由玩家主打


Dealer: E
Vul: Both

South West North  East
                   P
  P    3H    3S    P
 4S     P     P    P


S 8 6 4
H J 2
D J 3
C A K J 8 5 2


S A K J 9 7 2
H 9 3
D A K 5 2
C T


敵方打兩圈紅心後打出小D, 手裏DA吃住。然後我打出SA看看分佈, 左敵打出S5, 右敵卻墊出C6! 假設旁門無失張, 則只能再輸一磴王牌給左敵的 QT3。為了投入左敵, 先要縮短手中王牌的長度(好似係), 因此我手中打出DK, 然後夢家王吃一張方塊, 兌然CA, 然後手中王吃一張草花。之後再交叉王吃方塊和草花, 形成以下局勢:


         S -
         H -
         D -
         C K J 8
S Q T 3
H -
D -
C -
         S K J 9
         H -
         D -
         C -

然後手中打出S9, 投入左敵, 成功以KJ吃死他的Q3。


全手牌:
            S 8 6 4
            H J 2
            D J 3
            C A K J 8 5 2
S Q T 5 3                   S -
H K 8                       H A Q T 7 6 5 4
D Q 9 8 6                   D T 7 4
C Q 4 3                     C 9 7 6
            S A K J 9 7 2
            H 9 3
            D A K 5 2
            C T


不過如果AI第3圈再出紅心的話應該會很糟糕

Wednesday 9 February 2011

Sprague-Grundy Theory

Theorem: If G = g1+g2, then sg(G) = sg(g1)^sg(g2)

Proof:
Base case: If sg(g1) = sg(g2) = 0, then G is a P position, which has sg value 0 = 0^0

Induction: We have to prove
1. If sg(G) = v, then sg(G') != v if G → G'
2. If x < sg(G), then there exists G' where G → G' and sg(G') = x

Part 1
Assume G = g1+g2. WLOG, let G' = g1' + g2, by definition, sg(g1) != sg(g1')
Hence sg(G) = sg(g1)^sg(g2) != sg(g1')^sg(g2) = sg(G')

Part 2
Assume sg(g1) = A, sg(g2) = B, sg(G) = C and A < B
If we write A and B in binary representation, we have
A = an an-1 ... 1 ... a2 a1
B = bn bn-1 ... 0 ... b2 b1
and the bits of A,B before the 1 and 0 are same.

Let x < C. Consider x^sg(g2), we have
  C = cn cn-1 ... 1 ...
  x = cn cn-1 ... 0 ...
x^B = an an-1 ... 0 ...
Hence x^B < A. By definition, there exists g1' where sg(g1') < sg(g1) and sg(g1') = x^B.
Assume G' = g1'+g2, we have sg(G') = sg(g1')^sg(g2) = x^B^B = x.
Therefore G' exists.

Wednesday 26 January 2011

CodeForces Contest #53

題目
Scoreboard

A - Square Earth?
看了兩次才看明題目, 我的做法是給每一點一個label, 最後兩點相減
看到很多人都用分case的方法, 但不少人寫漏了case, 因此得到了不少hacking 分:D


B - Martian Architecture
我的做法是先找出每一點的高度, 對於每一個update (a,b,c), 可寫成
add[a]+=c;
chg[a]++;
add[b+1]-=c+a-b;
chg[b]--;
之後traverse一次array便可求出每一點的高度

Submit 第一次錯了, 但又找不到bug, 用了5分鐘才發現是把所有query的答案加起而不是續個output...
Hacking 時發現有 O(QM) 的做法, 十分簡潔


C - Array
數increasing+decreasing sequence的數目, 由於想不到公式, 因此先找出細case的答案, 然後當然是OEIS :D
得出公式是 C(2n,n)-n
老老實實, 答案要mod P, 因此要找 n! 的 inverse, 其實上了CSCI2110 才懂做的
後來發現每個dp[n][k]都對應 C(n+k-1,n), 總算接受了條公式


D - Journey
其實是問所有pair的total path length
對於每點 (X,Y), 計算在 total path 中 X 和 Y 分別被加和減了多少次
但有些path 不是走 shortest path 的, 因此要對每條這樣的 path +2
很可惜地, 我漏數了一些 case, 因此在 system test 中 fail 了

最後由於有7個hacking 和很多人也 fail 了 D (pretest 很弱), 離奇地排到第 15
也升了紅色:D

CodeForces Contest #51

題目
Scoreboard

A - Flea travel
直覺是當 t>N 就不會再去一些未去過的 node, 因此用O(N)頹做就submit了
後來再check, 發現只有 N 是 2 的 power 時才會行哂所有 node


B - Smallest number
應該有一些 greedy 方法, 不過由於懶加上只有4個數字, 就用vector 暴力枚舉
後來看到別人一些「正解」的方法: 加則加最大的兩個數, 乘則乘最小的兩個數


C - Pie or die
在紙上畫畫下, 發現/覺得只要考慮最接近邊界的一個點
第一次submit時是判斷距離<=3, 過不到pretest, 才發現應該是距離<=5
(其實這個錯頗幸運的, 因為如果寫距離<=4 是過到pretest 的)


E - Very simple problem
由於 D 是看似很難的數論, 又發現E 是geom, 便覺得可以一試
E 是 given 一個 convex polygon 和一點 p (保證不在 polygon 任意兩頂點連成的線上), 問有多少種方法選 polygon 的三點形成一個三角形使得 p 在三角形內



做法: 先預處理每一個頂點連到該點的線左邊有甚麼點 (如圖, Right(E) = {A,B,F})
我用binary search 做, 但其實可以一度做一度 rotate

然後, 枚舉三角形其中一點
假設其中一個包含 p 的三角形 XYZ, 必有 Y in Right(X) 和 Z in Right(Y)
這個可以用類似 partial sum 的方法做 (方便起見, 我寫得時侯是由 1 到 2n 的)
但也會數了像 EFA 的三角形, 所以最後要減去 C(|Right(x)|,2)

由於做到 E, 使得排名很幸運地入到頭 20, 開心了好一會

Thursday 20 January 2011

Xian 2006 - Gargoyle

雖然是上星期做的題目, 但還是想記錄下來
是 Lower Bound Min Cost Equal Flow

首先, 要找出 equal edge set 流量的 feasible range
根據論文[1], 這個 range 會是連續的, 即是 [0, u] 的 form
但是, 這題有 lower bound 的限制, 所以 range 應該會是 [l, u]

然後就想找 feasible range, 分別對上下界做 binary search
但是, 在做 binary search 時需要知道是大於 upper bound 還是小於 lower bound
一開始完全沒頭緒, 後來觀察到兩種情況下不滿流的邊是不同的, 就解決了這個問題

然後有一點要注意, equal edge set 取最小可行值 不等於 最小費用
再一次根據論文, cost 在 [l, u] 中是一個 convex function
所以可以用 ternary search 去找 min cost


[1] Algorithms for the Simple Equal Flow Problem, Ravindra K. Ahuja, James B. Orlin, Giovanni M. Sechi, Paola Zuddas

Saturday 8 January 2011

URAL 1043 - Cover an Arc

First, find the center and the radius of the circle.
Since we are looking for a bounding rectangle, we need to calculate minX, maxX, minY, maxY.

Intuition: Just compare with the up-most, leftmost, rightmost and the down-most point of the circle!
Next, we have to determine whether a point on a circle is on an arc.

Arrange the two ends of the arc A,B such that A->B is clockwise.
To check whether P is on the arc, just see whether triangle APB is clockwise or not, which can be easily done by cross product.

Last Bug:
mnx = (int)(mnx+1e-10);
mny = (int)(mny+1e-10);
mxx = ceil(mxx-1e-10);
mxy = ceil(mxy-1e-10);

Correct version:
mnx = floor(mnx+1e-10);
mny = floor(mny+1e-10);
mxx = ceil(mxx-1e-10);
mxy = ceil(mxy-1e-10);

Incorrect version won't work with negative numbers..

Friday 7 January 2011

URAL 1130 - Nikifor's Walk


好像是很經典的題, 題解十分巧妙
做法在這裏

回溯答案我用了tree去記錄, 如果merge i+j, 則由i到j連一條weight 0的edge; 如果merge i-j, 則連weight 1的邊, 最後從source做一次dfs
其實那些properties對我來說並不明顯, 所以還是在這裏做個記錄吧


Claim 1. For any two vectors u,v where |u|,|v| <= L, either |u+v| <= sqrt(2)*L or |u-v| <= sqrt(2)*L

Proof.
|u+v|2 = |u|2+|v|2-2|u||v|cos(θ)
|u-v|2 = |u|2+|v|2+2|u||v|cos(θ)
In either case, the square of magnitude will not greater than |u|2+|v|2 = 2*L2


Claim 2. For any three vectors length not greater than L, it is always possible to choose 2 of them such that the length resultant vector performing addition OR subtraction is not greater than L.


Proof.
I seen a proof on other's blog using the formula above, using the fact that there must exists a θ >= 120 degree.

Let three vectors be v,w,u.



Let the brown vector = v.
If v+w or v+u falls in yellow, then the length of v+w or v+u <= L
Else if v+w or v+u falls in red, then the length of v-w or v-u <= L
Else, v+w and v+u falls in blue or green, then the length of w+u or w-u <= L

Tuesday 4 January 2011

IOI 2008 Pyramid Base

揼了 200 行 code
應該是 IOI 有史以來 code length 最長的題目

其實咁複雜是因為 CASE 3 和 CASE 1, 2 的 approach 是不同的, 所以要分開兩段 code 去寫
做法分為 (1) Budget≠0 (2) Budget=0

對於(1), 可以 O(P * lg(P)* lg(Min(W, H)) 解決
對於(2), 可以 O(P * lg(P)) 解決

(1)
對答案做 binary search, 設 search length = d
想知有冇得 cover 一個 d * d 的 square 等同於將每一個 obstacle 向左和向下延伸d格, 然後睇下有冇一格個cost ≤ budget
用 segment tree 實現, 每個 node 記住 cover 和 best

(2)
對於 bugdet = 0, 即是要找全空的最大正方形
方法是, 用兩支指針指著 x1, x2, 每次 x1++ 就增加 x2 使得在 [x1, x2] 中最長的連續空白 ≥ (x2-x1+1)
也是要用 segment tree, 每個 node 記 cover, left max, right max, max

由於 W, H 可以去到 1,000,000, 所以一是離散 y 軸, 或者動態開樹
動態開樹應該比較易寫, 出錯的機會也較低

Saturday 1 January 2011

2010比賽總結


CCC Stage 1

基本上5條都識做, 係第5條input非常煩膠, 但出來的成積只有58/75, 比想像中低很多, 雖然也是第一
雖然CCC不是甚麼大比賽, 也撞了AL沒去stage2 (而且覺得暑假已經會去UW, 去年都去過)
很快便淡忘了

TopCoder High School

頭500有T-shirt, 但參加人數<500, 所以好像沒有甚麼壓力
R1,2打得頗不錯的, 但R3,4卻是悲劇, 印象中兩次也錯了些很低級的錯 記得打得最好的一次入到TOP25的

IOI/NOI TFT

第四次玩TFT, 這次做完時的感覺很差, 而出來的成積比想像中又是低了很多, 可能RP高剛好可以去IOI
第4條的bug非常低級, 真是太感激CTLi第3條讓我水到90分了, 否則便兩手空空而回
最後不得一提, 其實我連續3年TFT第3
總覺得自己這兩年的TFT都發揮都很差, 可能是緊張吧

Google Code Jam

R1a非常順利, 以滿分進入R2
而R2剛好就是TFT的晚上, 不知怎麼的在HKU lab打, 打到一半又要回家, 結果當然就是非常的差, 而且可能是TFT用盡了RP, 加上十分疲累, 竟然rank 502 (頭500入R3)
幸好後來有2個人被DQ (有一個更是在R3開始前數分鐘才被DQ), 入到R3, 不過也不是打得很好
總括來說就是實力不足, 對著題目無從入手

IOI 2010

出發時剛好去完細o, 可能因為不夠睡弄得有點病, 幸好在機上長睡後便沒事
每年去IOI的感覺都不同, 一開始總覺得和其它三人有點不熟, 但最後的效果很好很有趣
以食物來說, 今年的最難吃。不過其實我很享受去cafe, 酒吧和蒙古燒那三餐 (不論是食物還是吹水方面)
day1 打得還不錯的, 雖然rank只有4x, 但其實分數差距很小, 而且再打也應該差不多
day2 回想很失策。maze那題聽完Fai的做法, 就覺得自己浪費了2小時去opt果幾分, 而且我覺得自己有機會去想到safeit的
雖然只是假設性, 但好像因此而灰了一段時間
最終也沒能取得IOI金, 十分遺憾

第一年NOI, 銅2, 差一點銀
第二年IOI, 銀4, 差一點金
不過最接近, 最有機會IOI金的還是IOI09, 其中salesman我做了85便去想region, 但那15分本應是唾手可得的, 十分遺憾
三次IOI和一次NOI的經歷是我十分喜歡的, 雖然回想起來4次也表現得不好(用ideal case的角度看), 但那些時光真是十分快樂

Jakarta Regional

IsolatE第一場實戰, 不少失誤, 但294AC真的很興奮
總結是IsolatE潛力很大, 進步空間也很大

KaoHsiung Regional

好像除了開局時做的簡單題外就沒有了
B過不到是我的責任, 雖然不是說過就能過, 但也顯示了我的經驗不足和實力不足


總括來說, 這一年的比賽好像沒有哪個是滿意的, 即是說2011還要繼續努力