Problem
將一張 rgb 表示的彩色影像變成灰階影像。
套用公式 round((r + g + b)/3)
得到新的像素色彩。
Sample Input
|
|
Sample Output
|
|
Solution
|
|
將一張 rgb 表示的彩色影像變成灰階影像。
套用公式 round((r + g + b)/3)
得到新的像素色彩。
|
|
|
|
|
|
一天,liouzhou_101 去打印店裏打印了幾張複習資料,花了 4 毛錢,他給了店主1張塊錢的鈔票,結果店主補了他兩枚硬幣,一個5毛錢,一個 1 毛錢。
在走回宿舍的途中,liouzhou_101 一直在想一個問題,5 毛錢的硬幣和 1 毛錢的硬幣哪個更公平?所謂公平,就是指將一枚硬幣拋擲 1 次,他正面朝上的概率是 12,反面朝上的概率也是 12。
結果他一會去就把1毛錢的硬幣拋了 1000 次, 記下來有 531 次正面朝上。然後他突然說道:“這硬幣不公平!!!”
真的不公平嗎?他希望你計算一下出現這種情況的概率。
|
|
|
|
跟柳柳州互相出題目,已經來到了第 n 天,儘管我出的都是垃圾跟搬運題目,一出題被電得好愉悅,出在多的垃圾題都電不到柳柳州。
在擲硬幣找區間次數 $[a, b]$ 的機率,由於是離散的統計上就只能推組合數學,但又不是曲棍棒的模型 (Hockey Stick Pattern),算了先手動窮舉,用 Stirling’s formula 計算組合,後來發現有幾組數據有問題。
當 n 太大的時候,機率分布就相當稀疏,直接套用數值積分,直接去積分自然分布得到公式稍微困難,利用 simpson 或者是 romberg 去解決,但這樣還會有一個問題,只有在平均值的部分機率非常高 (類似離散的 00000100000),導致自適應辛普森積分會判斷錯誤,提醒剖半積分後測資就正確了不少。似乎合作出了一個可怕的題目,儘管如此,還是得用 mathlab 或者是 wolframalpha 來協助測資的檢驗,剩下的部分就交給柳柳州了。
關於自然分布 (normal distribution):
期望值 $E[x] = \sum_{k=1}^{n} k \binom{n}{k} p^k (1-p)^{n-k}$,消階層之後提出,計算後得到 $E[x] = np$。
而標準差 $\sigma$ 先從變異數下手
接下來直接帶入自然分布的公式,參數 $(\mu, \sigma)$,特別小心使用辛普森積分 $[a, b]$ 時,由於問題是離散的,要改變成 $[a - 0.5, b + 0.5]$,防止 $a = b$ 時造成積分錯誤。
特別感謝學弟 firejox 的數學指導。
不久之後,firejox 說道內建函數 erf()
可以解決積分問題,詳見 wiki Gauss error function,因此這一題也可以不寫辛普森積分,套用內建函數在不到 10 行內解決此題。
|
|
|
|
大學上課是怎麼回事的呢?談論到學期成績計算,很多奇聞軼事可以說的,例如教授任選三題批改、同學任選三題作答、滿分三百、沒有考試、 … 等。筆試類型的考試只是最常見的一種,還有所謂的多才華加分,例如上台報告、舉手發問、參與展覽、參加競賽、 … 等。
不幸地,某 M 修了一堂怪課,教授每一堂課結束後總是會大聲宣揚「葛萊分多加 5 分」對於需要不斷複習演練的某 M 而言,這門課的即時評分方式讓其非常挫敗。神奇的是,有一次教授這麼問同學「給一序列,請計算眾數、平均數、中位數,答對加分。」某 M 剎那間傻住,大學的學期成績可以用這種問題獲得,當他在懷疑這個問題時,問題早已被同學回答走。
某 M 非常不甘心,計算眾數、平均數、中位數就能夠加分,要求只是 n = 10 的序列。既然加分有理,出題吧!
平均數、中位數可以藉由區間總和、區間 K 小問題來完成,現在來解決眾數。
給定一個長度為 $n$ ( $1 \le n \le 100000$ ) 的正整數序列 $s$ ($1 \le s_i \le n$),對於 $m$ ( $1 \le m \le 1000000$) 次詢問 $l, r$,每次輸出 $[s_l, \text{... },s_r]$ 中,出現最多次的次數以及有多少種數字出現最多次。
|
|
|
|
眾數區間查找 Range mode query 性質可以參考維基百科。
在這一題中,這裡提供三種解法,但我的寫法中只有莫隊算法可以通過,其餘算法受到時間跟空間上的限制,需要額外的優化,細節就不多做說明:
由於這一題目標不是找到眾數為何 (這牽涉到最小字典順序),而是找眾數的出現個數和有幾種眾數可能,莫隊算法會快於其他算法。若是要求最小眾數莫隊算法需要 $O(N^{1.5} \log{N})$,分塊在線 1 也是 $O(N^{1.5} \log{N})$。
分塊在線 2 在此題不僅僅遇到記憶體過大,只好鬆弛 $L$ 來壓低記憶體用量,但增加時間需求,時間上慢個 10 倍以上。
|
|
|
|
|
|
「偽物比真物更有價值」—貝木泥舟
「真物和偽物一樣有價值」—忍野咩咩
「偽娘比真娘更有價值」—精英島民
任兩個物品的相似度$sim(A, B) = \frac{|A \cap B|}{|A \cup B|}$,換句話說把 $A$ 具有的特徵和 $B$ 具有的特徵類型取交集、聯集個數,相除就能得到其相似度。例如有 5 個特徵,若 A 表示成 11001、B 表示成 01100$sim(A, B) = \frac{|{2}|}{|{1, 2, 3, 5}|} = 0.25$。
現在盤面上有 N 個物品、M 種特徵,請問相似度大於等於 0.8 的相似對數 $S$ 有多少種。為了讓這一題更有趣味,算法允許偽物,輸出$\frac{S}{N(N-1)/2} \times 100$。
|
|
|
|
利用 std::bitset
加速交集和聯集運算,將數個屬性壓縮到一個 32-bits 單位,然後藉 bitcount 盡可能在 $O(1)$ 的時間內完成,就有機會通過這一題。一般的 $O(N^2 M)$ 比 $O(N^2 M/32)$ 慢個五六倍。
此外,特別小心浮點數計算誤差,5.0/4.0 >= 0.8 == false
,用乘法判定大於閥值的操作。
關於 LSH 的部分,還在進行測試,若 signature 計算太慢,還不如直接暴力法,若能分散找到 signature 或者是預先有辦法處理好,那分桶計算就會好一點。
|
|
曾經有一部採訪影片《BBC 紀錄片:別和日本人談性 No Sex. We’re Japanese.》在網路上流傳,其中有一段談到虛擬遊戲中的生活,不少男性以遊戲中的女角發生關係,其中以一款遊戲「Love Plus」為大宗,即使是擁有現實和虛擬的生活,若要選擇其中一方站,不少男性仍然「我選擇死亡」回答。
現在先不解決男女雙方的問題、在彼此關係上要如何運作,如何回到早些年沒有遊戲機、沒有網路、更沒有虛擬女友的交際生活,只有同性朋友要怎麼交流呢?於是有一場專門為這些男性舉行的一場交友會,規則如下所述:
請問每一個時刻下,有多少穩定對朋友。
|
|
|
|
IPSC 2015 F 那一題發生於男女雙方都會進行聯集,而這一題只有男方會進行聯集。
合併兩團男時,只有下標 (女友類型) 相同會成為穩定對,可以利用合併排序來完成,能發生合併表示男的彼此之間不認識,只要考慮有多少女方相同即可。每一次將小堆合併到大堆中,由於要計數合併複雜度需要 $O(min(|A|, |B|) \times \log N)$,若搭配 hash 可以降到 $O(min(|A|, |B|)$。一般并查集 joint 複雜度為 $O(1)$,整體操作只需要 $O(N)$,但為了要計數,整體的複雜度為 $O(N \log N)$。
可以選擇合併排序來完成,每一次把兩堆的女方列出來,把兩堆相同類型的次數相乘,列出來可以循序做,或者是串列完成,每一次保證堆裡面的女方順序是由小排到大,合併複雜度就為 $O(|A| + |B|)$,均攤下複雜度為 $O(N \log N)$,當測資不夠隨機複雜度會掉到 $O(N^2)$,情況是每一次只把大小為 1 的堆合併到大小 i-1 的堆。
在測資隨機生成下,第二種作法會來得比第一種快。第一種做法要搭配 ordered_map
或者是 unordered_map
,寫起來會比較不方便。
|
|
在 2015 年 6 月的 Facebook 上,不少以「靠北」為前綴命名的粉絲頁面,就如 靠北工程師 為例,不少業界工程師匿名在上面抱怨工作過時、主管、生活 … 等。突然有一篇 #靠北工程師7257 抱怨著編程競賽的零零種種,從回應中能明白存在業界工程師不清楚編程競賽,以 UI 介面、cmd 指令 … 等方式理解比賽的目標、運行。
網路處處有答案,演算法和資料結構到底重不重要?抄下來能用就行,大部分的要求是不講求效率的,但對於曾經在編程競賽待過一陣子的小夥伴而言,看到他們的理解方式開始感到憤憤不平,進行了一陣子的爭吵。
過一陣子,大批的學生開始進入 靠北工程師 裡發文,開始爭論學校、系所哪個是比較有未來的,突然間有一位資管系的同學發問這一道算法題 #靠北工程師7780 ,結果一不小心就看錯題目,把種類數誤看成個數,於是討論了不少其他的算法來完成,現在就把這個問題交給你。
用各種算法解決這個誤解的題目。
Autumn 和 Bakser 又在研究 Gty 的妹子序列了!
但他們遇到了一個難題,對於一段妹子們,他們想讓你幫忙求出這之內美麗度 $s_i \in [a, b]$ 的妹子個數。為了方便,我們規定妹子們的美麗度全都在 $[1,n]$ 中。
給定一個長度為 $n$ ( $1 \le n \le 100000$ ) 的正整數序列 $s$ ($1 \le s_i \le n$),對於 $m$ ( $1 \le m \le 1000000$) 次詢問 $l, r, a, b$,每次輸出 $[s_l, \text{... },s_r]$ 中,權值 $s_i \in [a, b]$ 的個數。
|
|
|
|
相較於 b414. BZOJ 3809 Gty 的二逼妹子序列 解法會相對多樣,單純計數就會變得比較簡單。
在這一題中,這裡提供三種解法:
ver_b - ver_a
查詢線段樹區間 $[l, r]$ 的總和。由於是計數符合區間減法才能這樣做,否則持久化線段樹還要套別的小技巧來完成。補充一點,雖然 KD-tree 效能是 $O(\sqrt{N} + K)$,它也支持 range searching,但必須搭配 report K 操作,那個 $O(\sqrt{N})$ 的花費是伴隨著 report 存在,因此單一筆計數詢問是無法達到 $O(\sqrt{N})$,天真的我寫下去直接 TLE。
|
|
|
|
|
|
Autumn 和 Bakser 又在研究 Gty 的妹子序列了!
但他們遇到了一個難題,對於一段妹子們,他們想讓你幫忙求出這之內美麗度 $s_i \in [a, b]$ 的妹子的美麗度的種類數。為了方便,我們規定妹子們的美麗度全都在 $[1,n]$ 中。
給定一個長度為 $n$ ( $1 \le n \le 100000$ ) 的正整數序列 $s$ ($1 \le s_i \le n$),對於 $m$ ( $1 \le m \le 1000000$) 次詢問 $l, r, a, b$,每次輸出 $[s_l, \text{... },s_r]$ 中,權值 $s_i \in [a, b]$ 的權值種類數。
|
|
|
|
解決區間內數字在某個值域內部的種類數。
前情提要 ,如果單純問區間種類數 (獨特),可以轉換成找區間內部有多少數字大於右端點,要預處理每一個數字的下一個相同數字的位置,只要符合大於右端點的條件即為獨特。可以使用持久化線段樹來做這件事情,依序加入序列數字,貪心去保留最右側的相同數字是獨特的,藉由多版本的區間相減來完成。
現在特別要求在某個值域內部,那就沒有好方法可解,可以使用莫隊下去完成。但是莫隊算法在區間轉移 (example [l, r] to [l, r+1]
) 的效能要縮小到 $O(1)$,若使用一般樹結構,莫隊算法會衰退到 $O(N^{1.5} \log N)$,還不如修改快一點 $O(1)$,詢問慢一點 $O(\sqrt{N})$,將值域使用塊狀表方式記錄,來達到 $O(N^{1.5} + Q \sqrt{N})$
|
|
寫題目不只會遇到算法複雜度問題,還會遇到語法上的瓶頸,了解更深入的作業系統架構、語言特性,了解每一個函數的實作方法,就能把代碼效能發揮到淋淋盡緻。當然,對於代碼轉成執行檔的最佳化技巧也是如此,接下來就來做個基礎題吧。
現在請處理一個偽隨機數計算,輸出前 $m$ 個值。
$x_{i+1} \equiv x_{i}^{2} \mod n$有興趣的同學,可以查閱 Blum Blum Shub (BBS) Generator 相關隨機數算法。
|
|
|
|
手動轉字串,減少函數 printf()
的呼叫,一次將答案吐出來便可以達到加速,由於有一部分時間都花在取模,速度最多提升個兩到三倍。
用 putchar()
速度也會比 printf()
快一點,但沒有實作 buffer 來得快。
|
|
一個長度為 n 的序列,支持兩種操作:
|
|
|
|
在討論用一些雜七雜八的樹類結構去跟莫隊算法搏鬥之餘,用了轉幾何方向去兜資料結構,隨後發現題目尋找的是 unique 而非計數,因此很多想法就垮台,當然出成另一道題目也是不錯。決定尋找其他想法!
整體二分是什麼呢?假設操作只有修改、詢問,不包含插入、刪除,而且詢問是一個數值結果,這個數值結果可以藉由二分 + 掃描來完成,那就可以使用整體二分來離線支持。
對答案值域分治,將相關操作分治在一起,同時要保留順序性,分治過程中會不斷地累加每一個詢問的掃描數值,最後滿溢時紀錄答案。每一個操作最多在 $\log \text{MAXV}$ 層計算,因此複雜度是 $O(Q \log \text{MAXV})$。
好處是可以用常數較低的結構,所以會比較快?
這一道經典題有很多作法,如持久化線段樹、塊狀鏈表、歸併樹、劃分樹、 … 等。其中能支持修改的有塊狀鏈表、複雜的持久化線段樹 (主席樹)。
帶修改的區間 K 小,概略說明二分答案 $x$,然後去查找小於等於 $x$ 的數字在區間 $[l, r]$ 內出現的次數是否大於等於 $K$。然後修改元素有加入跟移除,二分答案 mid,要將加入、移除會影響的 $A[i] \le mid$,加入或移除時對該數字的索引值 $i$ 建造統計方案。
對於(位置, 值) $\left \langle i, A[i] \right \rangle$ 來說,一開始的前 $N$ 個操作是加入 $\left \langle i, A[i] \right \rangle$,二分答案時,用一個 binary indexed tree 去維護 index 的個數,也就是說,對於修改元素 $\left \langle i, A[i] \right \rangle$ 相當於在二分答案 mid 時,插入 BIT.add(i, 1)
,那對於區間詢問,相當於查找 BIT.query([l, r])
如此一來就能知道區間 $[l, r]$ 在 mid 以內有幾個數字符合。
假設計數大於 k,詢問往左放,反之扣除已知 mid 以內的數量,詢問往右放,如此一來就完成了。
|
|
維護一個並查集的操作,並且支持版本回溯。
|
|
|
|
持久化概念,相當於維護 parent[]
陣列的版本,這一點可以利用可持久化線段樹來維護。
並查集的查詢功能不修改 parent[]
陣列,合併操作卻有可能修改數個 parent[]
,為了降低記憶體用量,盡可能少用路徑壓縮這個技巧,雖然在一般並查集都會使用這個來加速,否則很容易變很慢,是因為持久化是會拉低速度,因為持久化需要 $O(\log N)$ 的時間去更改 parent[]
,單筆路徑壓縮長度為 $M$ 個點,需要 $O(M \log N)$ 的調整,$M$ 在並查集中是常數類。
詢問不多時用啟發式合併就好,將小堆的元素合併到大堆中。效能會比較好。
|
|