{%hackmd @lumynou5/dark-theme %} # 競程總覽和題單 和各類應用常見演算法資結 <font color="red">**打到一半 我整理一下**</font> 請善用左邊跳轉跟ctrl+f <font color="orange">**關於競程**</font> 下列討論都以c/c\+\+為主 python(本文默認py3)建議當特殊功能輔助用 另開一類 ~~寫java建議棄賽~~ 不是啦jvm真的偏慢 有的競賽跑不過or很容易卡常 <font color="orange">**關於應用**</font> c可以做 但很難 不過好處永遠是快 c\+\+比較容易 而且也蠻快 還有OOP跟STL可以用 python應用比較特別 除了網頁/字串我暫時沒什麼想法 java作為老牌網路和應用軟體常用語言 篇幅不小 ~~跟競程完全相反~~ 速度也還行 又能跨平台 除了競程常見四類 js和web asm也很重要 tcp/ip可以學一下 另外資料庫也是一類 順便把作業系統與編譯器的資料一起放一放 ~~想不開一起來寫一個新語言~~ ## 分類 ![](https://hackmd.io/_uploads/rJAgtLvA3.png =65%x) 借一張吳邦一教授(就ap325作者)的ppt 雖然我的分類有點小小的不同 <font color="orange">**基礎類**</font> apcs觀念1\~5實作1\~2or3 &nbsp; &nbsp; 肯定要會吧 不然你跟我說你學過程式? <font color="peru">語法,陣列</font> &nbsp; &nbsp; 看起來可以很簡單 但是可以非常難 要有點數感找關係比較容易 <font color="peru">遞迴</font> &nbsp; &nbsp; 前兩個會了 那來學學共通語言 討論演算法跑多快 <font color="peru">演算法複雜度和主定理</font> &nbsp; &nbsp; 這沒什麼問題吧 常常會有問題叫你排序 <font color="peru">排序</font> &nbsp; &nbsp; 各種找東西 通常有排序過 用一些單調性求解 <font color="peru">二分搜,外掛二分搜,三分搜</font> &nbsp; &nbsp; 刷leetcode必備技能 不過除了實作STL或作業系統其實不那麼常見 <font color="peru">linked list</font> &nbsp; &nbsp; 局部最佳解可以得出全局最佳解時 除了貪心絕對不可能過 <font color="peru">貪心</font> <font color="orange">**常見競程類**</font> apcs實作3\~5 cpe3\~7題 &nbsp; &nbsp; <font color="lime">簡單數學</font> &nbsp; &nbsp; &nbsp; &nbsp; 演算法分析時 如果有<font color="pink">**機率性**</font> 或<font color="pink">**不同節點複雜度不同**</font> <font color="pink">**平均**</font>後可能總和更小 <font color="peru">均攤分析</font> &nbsp; &nbsp; <font color="lime">圖論</font> &nbsp; &nbsp; &nbsp; &nbsp; <font color="peru">圖的定義 </font>連通,有向,環,<font color="peru">樹</font>,帶權,<font color="peru">二分圖</font> &nbsp; &nbsp; &nbsp; &nbsp; 有了<font color="pink">**二元樹**</font> 就可以來做<font color="pink">**二分**</font> 透過左右一邊大一邊小做出<font color="pink">**二分搜**</font> <font color="peru">二元搜索樹</font> &nbsp; &nbsp; &nbsp; &nbsp; 在圖上要找東西 像是<font color="pink">**最短/長路徑**</font> 或符合某些條件的東西(說實話範圍很廣) <font color="peru">bfs,dfs</font> &nbsp; &nbsp; <font color="lime">資料結構</font> &nbsp; &nbsp; &nbsp; &nbsp; STL跟各類二元樹常用實作之一 有線性heap的特別版 還有treap的進階變體 <font color="peru">heap</font> &nbsp; &nbsp; &nbsp; &nbsp; 一樣是STL實作 map或set用 網路應用也很多 了解原理比較重要 <font color="peru">hash</font> &nbsp; &nbsp; &nbsp; &nbsp; 也是STL實作 map跟set用 用<font color="pink">**旋轉**</font>(雖然有點麻煩)做出<font color="pink">**類似數學歸納法的平衡**</font> <font color="peru">紅黑樹</font> &nbsp; &nbsp; &nbsp; &nbsp; tree+heap 樹的性質,堆的順序,紅黑樹的效果 有分割式能避免旋轉<font color="peru">treap</font> &nbsp; &nbsp; &nbsp; &nbsp; 方便好用又不用底層實作(還是要學啦) 大部分題目都很難單用陣列就解出 <font color="peru">STL</font> &nbsp; &nbsp; &nbsp; &nbsp; 也是STL裡的函數 雖然並不是資結 但說實話我不知道放哪 用來計算<font color="peru">字典序的下一項</font> &nbsp; &nbsp; &nbsp; &nbsp; <font color="pink">**輸入值域很大**</font>(像int)但總數不多 <font color="peru">離散化</font>(其實不是資結 但因為會用到資結就放進來) &nbsp; &nbsp; <font color="lime">遞迴和他們的進階(不太嚴謹啦 不一定要用遞迴 不過不要太在意)</font> &nbsp; &nbsp; &nbsp; &nbsp; 遞迴的時候一直<font color="pink">**重複算**</font>算過的東西嗎 那就把先算到的存起來吧 背後有個<font color="pink">**DAG**</font> <font color="peru">dp</font> &nbsp; &nbsp; &nbsp; &nbsp; 遞迴的時候 問題的答案從兩個<font color="pink">**不重疊**</font>的子問題求嗎 那寫完遞迴式就解完了 <font color="peru">分治</font> &nbsp; &nbsp; <font color="lime">區間問題</font> &nbsp; &nbsp; &nbsp; &nbsp; 需要求一整段的<font color="pink">**不會變**</font>的<font color="pink">**總和**</font>嗎 那就先算到頭的總和 再扣掉前面的總和 <font color="peru">前綴和</font> &nbsp; &nbsp; &nbsp; &nbsp; 相對的 需要一直對一段<font color="pink">**區間**</font>一起<font color="pink">**修改**</font>嗎 那就標記某點以後全部加/減一個數 <font color="peru">差分</font> &nbsp; &nbsp; &nbsp; &nbsp; 更廣泛的 如果問題是<font color="pink">**多次詢問**</font>不同區間的值(像極值) 列出某些區間再合起來 <font color="peru">稀疏表</font> &nbsp; &nbsp; &nbsp; &nbsp; 可是稀疏表不能<font color="pink">**修改**</font> 所以可以用一棵樹 不同層儲存不同的長度 然後去改樹 <font color="peru">線段樹</font> &nbsp; &nbsp; &nbsp; &nbsp; 線段樹<font color="pink">**區間改值**</font>要懶標 而且空間又大 可以擁有這些特性但<font color="pink">**空間n**</font> 不過<font color="pink">**適合區間和**</font> <font color="peru">BIT</font> &nbsp; &nbsp; &nbsp; &nbsp; 有了前兩棵樹和平衡樹 就可以解決<font color="pink">**二維區間問題**</font> 用<font color="peru">樹套樹</font> 但是好難我不會qq &nbsp; &nbsp; &nbsp; &nbsp; 看起來在<font color="pink">**樹上找最近共同祖先**</font>跟區間毫無關聯 但他就是能<font color="pink">**轉化成RMQ**</font>問題 <font color="peru">LCA</font> &nbsp; &nbsp; <font color="lime">區間問題 但是貪心</font> &nbsp; &nbsp; &nbsp; &nbsp; 計算時要窮舉 但是<font color="pink">**有些值用過就不用**</font>了(常有單調性) 維護左右兩點<font color="pink">**區間範圍**</font> <font color="peru">雙指針</font> &nbsp; &nbsp; &nbsp; &nbsp; 類似的 區間移動時 要<font color="pink">**跑一遍整個區間**</font> 要<font color="pink">**維護區間內的值**</font>(常用動態資結) <font color="peru">滑動視窗</font> &nbsp; &nbsp; &nbsp; &nbsp; 假設要考慮<font color="pink">**某點以前/後到底的所有值**</font> 並且某些<font color="pink">**單調性**</font>會讓一些值被跳過 用<font color="peru">單調棧</font> &nbsp; &nbsp; <font color="lime">區間問題 但是離線(好難qq 要意識到時間也是序列)</font> &nbsp; &nbsp; &nbsp; &nbsp; 區間問題除了每次操作分開處理 也能<font color="pink">**預先處理詢問重複**</font>的地方 最後一起算 <font color="peru">CDQ分治</font> &nbsp; &nbsp; &nbsp; &nbsp; <font color="pink">**離線**</font>後 對於<font color="pink">**二分**</font>問題 可用<font color="peru">整體二分</font> 把每筆<font color="pink">**操作分到該去的區間**</font> <font color="pink">**重疊**</font>的便可<font color="pink">**共用答案**</font> &nbsp; &nbsp; &nbsp; &nbsp; <font color="pink">**離線**</font>後 若可得相鄰區間解 可用<font color="peru">莫隊算法</font> <font color="pink">**排序詢問的區間**</font> 再從前面的區間往後面的爬 &nbsp; &nbsp; <font color="lime">字串和序列(不須連續但順序不能相反)問題</font> &nbsp; &nbsp; &nbsp; &nbsp; 要尋找<font color="pink">**最長的遞增/減序列**</font> 運用<font color="pink">**單調性**</font>進行<font color="pink">**二分**</font>可以有$O(nlogn)$ <font color="peru">LIS</font> &nbsp; &nbsp; &nbsp; &nbsp; 對<font color="pink">**兩個字串找最長共同序列**</font> 有<font color="pink">**dp**</font>解 但能<font color="pink">**轉化**</font>為二維LIS 再變為<font color="pink">**一維LIS**</font> <font color="peru">LCS</font> &nbsp; &nbsp; &nbsp; &nbsp; 對<font color="pink">**兩個字串做匹配**</font> 透過尋找<font color="pink">**子字串中重複**</font>的部分 快速跳到<font color="pink">**下一個匹配點**</font> <font color="peru">KMP</font> &nbsp; &nbsp; &nbsp; &nbsp; 尋找<font color="pink">**字串中最長回文**</font> 對每個點計算<font color="pink">**以前面的字為中心鏡像**</font>最長能多長 <font color="peru">馬拉車</font> &nbsp; &nbsp; <font color="lime">數學(含一點線性代數)和數論(離散數學或抽象代數)(台灣有點缺這方面 大家補一下)</font> &nbsp; &nbsp; &nbsp; &nbsp; 算多重加法=乘法 算多重乘法=冪次 <font color="pink">**冪次不是cpu基本運算**</font>怎麼辦 <font color="peru">快速冪</font>(有點線代) &nbsp; &nbsp; &nbsp; &nbsp; 公因數可以用<font color="pink">**輾轉相除法**</font> 但是為了其他目的(像除法跟取餘是同指令) <font color="peru">擴展歐基里德</font> &nbsp; &nbsp; &nbsp; &nbsp; 數學題/排組/總方案數 數字常超大 答案常模一個數 <font color="pink">**取模環境下除法怎麼做**</font> <font color="peru">模逆元</font> <font color="orange">**還沒寫進去類**</font> 快慢算法,baby-step giant-step,位dp,tsp,km二分匹配,Rolling Hash(Rabin Karp算法) suffix array 數學 https://oi-wiki.org/math/ 戴克斯特拉 佛洛伊德 Bellman-Ford Kruskal prim 最小生成樹 並查集 對頂堆 pb_ds A* 樹套樹 最近點對 反演變化 莫比烏斯反演 https://judge.tcirc.tw/Problems?page=5&&tabid=AP325 ,01背包 莫隊 <font color="orange">**應用類**</font> 競程不常見但應用常見 卷積,FTT &nbsp; &nbsp; <font color="lime">簡單數學(真的只有簡單運算啦)</font> &nbsp; &nbsp; &nbsp; &nbsp; <font color="pink">**超過int**</font>怎麼辦(金融) 只好陣列模擬 但java,python都自帶大數 競程不愛出 <font color="peru">大數運算</font> &nbsp; &nbsp; <font color="lime">數論類 延續中等類數論</font> &nbsp; &nbsp; &nbsp; &nbsp; 會開方了 那來學學<font color="pink">**對數**</font> 不過要先認識<font color="peru">原根</font> 之後就可以算<font color="peru">離散對數</font>了 資安加密需要 &nbsp; &nbsp; &nbsp; &nbsp; NTT 四叉樹,大數 各類網站 中一中電研 zerojudge leetcode codeforce atcoder 各類比賽 apcs cpe 學科能力競賽 npsc ncpc ista icpc ioi leetcode周賽雙周賽 CF atcoder ioi題庫 https://yuihuang.com/ioi/ 各類題庫 https://yuihuang.com/exercise/ OIwiki https://oi-wiki.org/ cses https://cses.fi/problemset/ ## 內文 ### 基礎類 語法不會 ~~那你去google語法啊在這裡做什麼~~ [runoob c](https://www.runoob.com/cprogramming/c-tutorial.html) [runoob c++](https://www.runoob.com/cplusplus/cpp-tutorial.html) [runoob python3](https://www.runoob.com/python3/python3-tutorial.html) [陣列](https://opensourcedoc.com/c-programming/array/) **題單:** 上面隨便挑個[zj基礎題](zerojudge.tw/Problems?tabid=BASIC#tab00)或[板中題](https://zerojudge.tw/Problems?tag=%E6%95%99%E5%AD%B8%E9%A1%8C)都能練 [**遞迴**](https://www.csie.ntu.edu.tw/~b98902112/cpp_and_algo/cpp02/recursion.html)給個[一題](https://zerojudge.tw/ShowProblem?problemid=c002)簡單題 然後一題[N皇后](https://hackmd.io/@YLowy/r1wIe9-DD)剪枝 跟[位元運算+lowbit版](https://zhuanlan.zhihu.com/p/22846106) 當你發現有東西重複計算 就代表可以去看dp了 **比較型排序** 包含 插入,泡沫,選擇 這三個看看就好 不實用 qsort(c內建),std::sort(c++內建) 快又實用 比較函式學一下 方便逆序或特殊結構 **非比較型排序** 包含 記數,桶排,合併 有時候會在特定題目用上 遇到或有點空就學一下吧 [**貪心**(第一段)](https://hackmd.io/@tcirc-40th/home/https%3A%2F%2Fhackmd.io%2F%40tcirc-40th%2Fry8pDcZdi)([像經典換硬幣](https://judge.tcirc.tw/ShowProblem?problemid=d042) 就你平常買東西那樣 另外給[一題](https://zerojudge.tw/ShowProblem?problemid=l243)好了) **STL** 去google前幾個就會有 包含 stack,queue,set,map,vector 這行最優先 很基礎 priority_queue(pq),unordered_set,unordered_map 上面變體 遇到難題就會發現你需要他 pair,list(同python默認list) pair是懶人福音 list特別情況才會用到(幾乎沒 也可換linked list) [**dp**](https://web.ntnu.edu.tw/~algo/DynamicProgramming.html)([像經典換硬幣](https://zerojudge.tw/ShowProblem?problemid=d904)) 有時候 **題單:** 超萬能的[ap325](https://judge.tcirc.tw/Problems?tabid=AP325#tab03) 全做完就對了 第一題裡面有講義連結 入門類只用到1~6章