Problem A - Knight Tournament (by nkhg)
有\(n\)個騎士、\(m\)場對決,原始騎士被編號\(1\)到\(n\),給你那\(m\)場對決的紀錄,每個紀錄會是\(l,r,x\)指編號\(l\)到\(r\)當中還沒遭到淘汰的騎士決鬥,並且編號\(x\)的騎士勝出。
最後請你對每個騎士輸出他是被誰打敗的(就是他出局的那一回合勝出的是誰),沒有被打敗的人請輸出\(0\)。(保證最後恰一個人獲勝、每個對決紀錄至少有兩個騎士參與)
題解:
我是用線段樹解這題,每次把那回被打敗的人的區間標記為\(x\),遞迴下去的時候如果那個區間已經被標記過,就不做事,否則就標記上去。仔細想想如果一個騎士被打敗好幾次,那麼一定是在最底層的那個標記被打敗的。(因為覆蓋到同一個點的標記,比較慢來的不可能被遞迴到底層)
時間複雜度:\(O((n+m)\log n)\)
其他做法:
後來看題解寫了兩個作法,而且都跟我的作法不一樣。
我在virtual的時候最先寫了個linked list的錯誤作法,慌亂之下沒有思考比較單純的作法,才會寫到線段樹。
tutorial作法一:
直接用一個set存現在還沒被淘汰的人,決鬥時就lower_bound左界然後一個一個掃過去,反正每個人被看過一次之後就會被拔掉了。(當然\(x\)本身是個例外,不過不影響效率)
tutorial作法二:
根據前一個作法,我們試著對每個騎士維護他的下一個還沒被淘汰的人是誰,然後使用路徑壓縮處理就好了。
Problem B - Xenia and Hamming (by nkhg)
給你兩個字串(保證一樣長),叫你輸出他們的漢明距離。
字串的給法是:
給\(n,m\)、英文小寫字串\(x,y\),表示字串是\(x\)重複\(n\)次與\(y\)重複\(m\)次。
(\(n,m\le 10^{12}, |x|,|y|\le 10^6\))
題解:
基於題目的保證,我們知道實際字串長度一定是\(lcm(|x|,|y|)\)的倍數,且配對狀況以\(lcm(|x|,|y|)\)的長度循環,因此只要思考\(lcm(|x|,|y|)\)的狀況再乘上某個倍數就好了。
令\(g=gcd(|x|,|y|)\),那麼我們發現在\(lcm(|x|,|y|)\)內,\(x\)跟\(y\)當中位置編號對\(g\)同餘的字元一定會配對到恰一次,而對\(g\)不同餘的一定不可能配對到。(理由自己想想看)
這時候因為字元集很小(26),所以直接開一條那麼大的陣列,把對\(g\)餘\(i,0\le i\lt g\)的分別處理一遍就好。
(賽中的bug都是long long,從乘法跟輸入分別WA了一遍)
code: http://codeforces.com/contest/356/submission/16777722
題解:
基於題目的保證,我們知道實際字串長度一定是\(lcm(|x|,|y|)\)的倍數,且配對狀況以\(lcm(|x|,|y|)\)的長度循環,因此只要思考\(lcm(|x|,|y|)\)的狀況再乘上某個倍數就好了。
令\(g=gcd(|x|,|y|)\),那麼我們發現在\(lcm(|x|,|y|)\)內,\(x\)跟\(y\)當中位置編號對\(g\)同餘的字元一定會配對到恰一次,而對\(g\)不同餘的一定不可能配對到。(理由自己想想看)
這時候因為字元集很小(26),所以直接開一條那麼大的陣列,把對\(g\)餘\(i,0\le i\lt g\)的分別處理一遍就好。
(賽中的bug都是long long,從乘法跟輸入分別WA了一遍)
code: http://codeforces.com/contest/356/submission/16777722
Problem C - Compartments (by nkhg)
火車上有\(n\)個包廂,每個包廂容量最大\(4\)人,現分別有學生\(0\)到\(4\)人,請問最少要讓幾個學生換位置使得每個包廂的學生數量都是\(0,3,4\)其中一個?
題解:
看到官方題解是做了一部分greedy之後,剩的直接枚舉,還寫說"You shouldn't come up with common solution. Else you should just to consider all possible cases."
不過我就是在virtual的時候把所有case寫出來的人XD
作法如下:
*1+2→3
然後會只剩下1或2,分兩邊,只剩下1的(照順序):
*1+1+1→3
*1+1+4→3+3
*1+3→4
*1+4+4→3+3+3
如果是只剩下2的(也是要照順序):
*2+2+2→3+3
*2+2→4
*2+4→3+3
*2+3+3→4+4
以上是全部了,我也不知道為什麼我這麼有耐心耶XDD
code: http://codeforces.com/contest/356/submission/16778167
題解:
看到官方題解是做了一部分greedy之後,剩的直接枚舉,還寫說"You shouldn't come up with common solution. Else you should just to consider all possible cases."
不過我就是在virtual的時候把所有case寫出來的人XD
作法如下:
*1+2→3
然後會只剩下1或2,分兩邊,只剩下1的(照順序):
*1+1+1→3
*1+1+4→3+3
*1+3→4
*1+4+4→3+3+3
如果是只剩下2的(也是要照順序):
*2+2+2→3+3
*2+2→4
*2+4→3+3
*2+3+3→4+4
以上是全部了,我也不知道為什麼我這麼有耐心耶XDD
code: http://codeforces.com/contest/356/submission/16778167