AACPOJ 寫筆記教學
為什麼要寫題目筆記?
寫競程題目筆記最主要的目的是未來回來複習時,能讓當時的你用最少的時間回想起整題的思路。如果只寫「這題是 DP」、「用線段樹」,幾個月後再看基本沒用;但如果筆記裡有思路鏈、關鍵觀察、陷阱紀錄,就能在幾分鐘內把整題重新建立起來。
一個好的筆記不只是解法紀錄,更是你自己的學習軌跡:哪裡卡住、怎麼突破、為什麼一開始想錯、下次遇到類似題可以套什麼模式。久了累積下來,就是你自己的「知識庫」。
一、筆記可以記什麼?
以下項目不是每題都要全寫,挑對未來的你最有幫助的就好。
1. 題目簡述(抽象化)
用一兩句話把題目的「數學本質」寫下來,把故事剝掉。例如:
- 不要寫:「有個人要送禮物給朋友⋯⋯」
- 改成:「給定陣列 \(a\),求最小的 \(k\) 使得 \(\sum a_i \le k\)」
這樣之後掃過筆記能一眼看出是什麼類型的題目。
2. 關鍵觀察 / 性質
這是筆記裡最有價值的部分。 寫下你在解題過程中「想通」的那一刻看到的性質:
- 「發現答案一定單調,可以二分搜」
- 「注意到 \(k\) 次操作後只有前 \(\log n\) 位會變」
- 「把問題轉成圖論:點代表狀態,邊代表轉移」
3. 思路演進
從樸素解到正解的演進過程,比只寫最終解法更有學習價值。例如:
- 最初想到 \(O(n^2)\) 暴力:每個位置枚舉⋯⋯
- 優化 1:發現重複計算,預處理前綴和 → \(O(n)\)
- 優化 2:觀察到單調性,可以用單調堆疊 → 最終 \(O(n)\) 實作更簡潔
4. 踩過的坑 / 常見錯誤
寫下你這次犯的錯,讓未來不再犯:
- 「沒開 long long」
- 「二分搜邊界 +1 / -1 寫錯」
- 「陣列開太小」
- 「輸出忘了換行」
下次遇到類似題可以當 checklist 用。
5. 類似題 / 延伸題
當發現這題和某題「套路一樣」時,互相連結起來:
這題和 CF 1234A 一樣是用字典序貪心,核心觀察相同。
6. 複雜度
簡短記錄時間/空間複雜度,方便之後判斷題目難度。
7. 標籤 / 演算法類別
方便之後用關鍵字搜尋:#線段樹 #區間 DP #圖論 #二分搜。
二、怎麼把筆記寫得整齊美觀?
AACPOJ 的題解、題目筆記、作業筆記都支援 Markdown + LaTeX,以下是常用語法。
標題分層
用 ## / ### / #### 分章節,結構清楚:
## 思路
### 關鍵觀察
### 實作細節
粗體、斜體、刪除線
**重點文字**、*強調文字*、~~刪除文字~~
顯示為:重點文字、強調文字、\(None\)刪除文字\(None\)
項目清單
無序清單用 -:
- 第一點
- 第二點
- 子項目(縮排兩格)
有序清單用 1.:
1. 第一步
2. 第二步
3. 第三步
程式碼
行內程式碼用反引號 `:
`O(n log n)` 的解法
多行程式碼用三個反引號,並一定要標記語言(才會有 syntax highlight):
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int n; cin >> n;
cout << n * n << '\n';
return 0;
}
```
數學公式(重要)
AACPOJ 使用 DMOJ 原生的 LaTeX 語法,不是一般的 $...$。共有兩種:
1. 行內數學:在文字中間插入公式,用 ~...~ 包起來。
源碼:
當 ~n \le 10^5~ 時,~O(n \log n)~ 的解法可以通過。
渲染:
當 \(n \le 10^5\) 時,\(O(n \log n)\) 的解法可以通過。
2. 獨立顯示數學:公式獨立置中顯示,用 $$...$$ 包起來,前後要空行。
源碼:
對於所有 ~i~,
$$\sum_{j=1}^{i} a_j \ge \lfloor \log_2 i \rfloor$$
這個式子始終成立。
渲染:
對於所有 \(i\),
\[\sum_{j=1}^{i} a_j \ge \lfloor \log_2 i \rfloor\]
這個式子始終成立。
禁止使用 $...$(單個 dollar)— DMOJ 的 MathJax 不認這個分隔符。
常用數學符號
左邊是你要寫的原始碼,右邊是實際渲染效果:
| 源碼 | 效果 | 用途 |
|---|---|---|
~\le~ ~\ge~ ~\neq~ |
\(\le\) \(\ge\) \(\neq\) | 小於等於、大於等於、不等於 |
~\to~ ~\Rightarrow~ |
\(\to\) \(\Rightarrow\) | 箭頭、推導 |
~\cdot~ ~\times~ ~\bmod~ |
\(\cdot\) \(\times\) \(\bmod\) | 乘法、取模 |
~\sum_{i=1}^{n} a_i~ |
\(\sum_{i=1}^{n} a_i\) | 求和 |
~\prod_{i=1}^{n} a_i~ |
\(\prod_{i=1}^{n} a_i\) | 求積 |
~\log n~ ~\sqrt{n}~ |
\(\log n\) \(\sqrt{n}\) | 對數、開根號 |
~a_i~ ~a^2~ ~a^{n+1}~ |
\(a_i\) \(a^2\) \(a^{n+1}\) | 下標、上標 |
~\frac{a}{b}~ |
\(\frac{a}{b}\) | 分數 |
~\lfloor x \rfloor~ ~\lceil x \rceil~ |
\(\lfloor x \rfloor\) \(\lceil x \rceil\) | 向下、向上取整 |
~\{a, b, c\}~ |
\(\{a, b, c\}\) | 集合 |
~[1, n]~ ~(a, b]~ |
\([1, n]\) \((a, b]\) | 閉/半開區間 |
~O(n \log n)~ |
\(O(n \log n)\) | 複雜度 |
引用區塊
用 > 放重點語錄、題意摘要、老師講過的話:
> 核心觀察:當 ~n~ 為偶數時,答案必然存在。
表格
比較兩種做法、列出時間複雜度、對照資料範圍特別好用:
| 方法 | 時間 | 空間 | 備註 |
|---|---|---|---|
| 暴力 | ~O(n^2)~ | ~O(n)~ | 可過 ~n \le 5000~ |
| 線段樹 | ~O(n \log n)~ | ~O(n)~ | 正解 |
水平分隔線
用 --- 隔開章節,讓長筆記有呼吸空間:
---
連結
[顯示文字](https://example.com)
三、一份好筆記的範例
以下是一個理想筆記的骨架(你可以把它當模板):
## 題目簡述
給定長度 ~n~ 的陣列,求最小化⋯⋯
## 資料範圍
- ~1 \le n \le 2 \times 10^5~
- ~1 \le a_i \le 10^9~
## 關鍵觀察
1. 答案對 ~k~ 具有單調性 → 可以二分搜
2. 對於固定的 ~k~,判斷可行性只需要一次線性掃描
## 思路演進
- **暴力**:枚舉所有 ~k~,~O(n^2)~ → TLE
- **優化**:二分搜 + 線性 check → ~O(n \log n)~
## 實作細節
- 二分搜範圍:`[1, max(a)]`
- `valid(k)` 函數:⋯⋯
## 踩過的坑
- ❌ 一開始把二分搜的邊界寫成 `l = mid` 導致 TLE
- ❌ 沒開 `long long` 導致累加時 overflow
## 複雜度
- 時間:~O(n \log V)~
- 空間:~O(n)~
## 核心程式碼
```cpp
bool valid(long long k) {
// ...
}
int main() {
long long lo = 1, hi = 1e9;
while (lo < hi) {
long long mid = (lo + hi) / 2;
if (valid(mid)) hi = mid;
else lo = mid + 1;
}
cout << lo << '\n';
}
```
## 類似題
- CF 1234A(同樣的二分搜套路)
- ABC 321D(延伸:加上 DP)
標籤:`#二分搜` `#貪心`
四、預覽你的筆記
在編輯題目筆記時,建議先在編輯框下方的預覽區確認排版,特別是:
- 數學公式有沒有正確顯示(不是顯示成原始
~...~) - 程式碼區塊有沒有正確的 syntax highlight
- 表格有沒有對齊
- 標題層級有沒有混亂
發現有問題再回去調整。預覽沒問題再存檔,才不會看到學期末發現以前的筆記一片亂。
小結
寫筆記的第一條準則:為了未來的自己寫。
記錄關鍵觀察、思路演進、踩過的坑,比抄下一份標解更有價值。再搭配 Markdown 的標題、清單、程式碼區塊、LaTeX 數學公式,就能做出一份回頭看依然能幫你重新理解題目的好筆記。