基礎模板
1 |
|
資料結構
BIT (Fenwick Tree / 樹狀數組)
用途:支援單點修改、前綴和查詢的資料結構。
複雜度:修改 $O(\log n)$、查詢 $O(\log n)$。
1 | struct BIT { |
用法:
1 | BIT bit(n); |
單點覆蓋(把位置 x 的值改成 y):
1 | bit.upd(x, -bit.v[x]); // 先扣掉舊值 |
簡化版 BIT(不需記錄原值,適合只做加法的場景):
1 | struct BIT { |
Segment Tree (線段樹 - 迭代式)
用途:支援單點修改、區間查詢的資料結構。比 BIT 更泛用(可處理 min/max/sum 等)。
複雜度:建樹 $O(n)$、修改 $O(\log n)$、查詢 $O(\log n)$。
以下為區間最小值查詢 + 單點修改版本:
1 | struct segment_tree { |
用法:
1 | segment_tree st(n); |
改成區間和:把所有
min改成+,初始值INF改成0。
Sparse Table (稀疏表)
用途:靜態陣列上 O(1) 回答區間 min/max 查詢(不支援修改)。
複雜度:建表 $O(n \log n)$、查詢 $O(1)$。
利用兩個有重疊的區間取 max/min 結果仍正確的性質(冪等性),可以 $O(1)$ 查詢。
1 | // 建表:st[i][j] = 從位置 i 開始、長度 2^j 的區間最大值 |
DSU (Disjoint Set Union / 並查集)
用途:維護不相交集合的合併與查詢,常用於判斷連通性。
複雜度:均攤 $O(\alpha(n)) \approx O(1)$。
基本版(含路徑壓縮 + 啟發式合併):
1 | struct DSU { |
附帶連通分量數 + 最大分量大小(適合需要即時查詢這些資訊的場景):
1 | struct DSU { |
不帶路徑壓縮版(需要可撤銷 / rollback 時使用,搭配啟發式合併仍為 $O(\log n)$):
1 | int find(int x) { |
Monotone Stack (單調棧)
用途:在 O(n) 內找到每個元素左/右邊第一個比它大或小的元素。
複雜度:$O(n)$(每個元素最多入棧出棧各一次)。
找每個元素左邊第一個比它小的位置(v 存的是下標,棧底放哨兵 0):
1 | vector<int> v, a(n + 1); |
最大矩形面積(histogram)- 雙 pass:對每個柱子找左右邊界,再算面積。
1 | vector<int> h(m), l(m), r(m); // h = 高度,l[j] = 左邊第一個 < h[j] 的位置 |
最大矩形面積(histogram)- 單 pass(在右端點處結算):
1 | vector<int> v, a(n + 2); // a[n+1] = 0 作為結尾哨兵 |
Monotone Deque (單調雙端佇列)
用途:在滑動視窗中 O(1) 查詢最大/最小值。
複雜度:整體 $O(n)$。
滑動視窗最小值(視窗大小在 [a, b] 之間):
1 | deque<int> q; // 存下標,隊列中的值單調遞增 |
同時維護最大值和最小值(固定視窗大小 m):
1 | deque<int> q, p; // q: 遞減隊列(max),p: 遞增隊列(min) |
圖論
BFS (廣度優先搜尋)
用途:在無權圖上求最短路徑、探索連通分量。
複雜度:$O(V + E)$。
最短路徑 + 路徑回溯(從節點 1 到節點 n):
1 | vector<vector<int>> v(n + 1); // 鄰接表 |
網格 BFS(上下左右四方向):
1 | int dx[4] = {0, 0, 1, -1}; |
0-1 BFS
用途:邊權只有 0 和 1 時的最短路,用 deque 取代 priority_queue。
複雜度:$O(V + E)$(比 Dijkstra 的 $O(E \log V)$ 快)。
權重 0 的邊放隊首(push_front),權重 1 的邊放隊尾(push_back):
1 | deque<tuple<int, int, int>> q; // {節點, 距離, 狀態} |
DFS (深度優先搜尋)
用途:圖的遍歷、連通分量計數、環偵測、拓撲排序等。
複雜度:$O(V + E)$。
連通分量計數(網格版,每個連通區域呼叫一次 dfs):
1 | int dx[4] = {0, 0, 1, -1}; |
Dijkstra (最短路徑)
用途:求單源最短路(邊權非負)。
複雜度:$O(E \log V)$。
1 | vector<vector<pair<int, int>>> v(n + 1); // v[a] = {{b, w}, ...} 表示 a->b 權重 w |
變體:同時記錄最短路數量、最少邊數、最多邊數:
1 | vector<int> dis(n + 1, INF), way(n + 1, 0), mn(n + 1, INF), mx(n + 1, 0); |
K-th 最短路(允許同一節點被拜訪多次,第 k 次到達即為第 k 短路):
1 | priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; |
網格 Dijkstra(Trapping Rain Water 2D:從邊界開始,向內推水位高度):
1 | priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<tuple<int, int, int>>> q; |
Floyd-Warshall (全源最短路)
用途:求所有點對之間的最短路。適合節點數少($n \leq 500$)的稠密圖。
複雜度:$O(n^3)$。
核心思想:$dis[i][j] = \min(dis[i][j],\ dis[i][k] + dis[k][j])$,依序考慮每個中繼點 $k$。
1 | const long long INF = numeric_limits<int>::max() / 2; // 注意用 INF/2 避免溢位 |
離線刪邊技巧:把刪邊反轉成加邊,每次加入新中繼點 $x$ 後用 $O(n^2)$ 更新:
1 | // 加入邊 (a[x], b[x]) 權重 w[x] 後,a[x] 和 b[x] 可作為新中繼點 |
Topological Sort (拓撲排序 / Kahn's Algorithm)
用途:將 DAG(有向無環圖)的節點排成線性序列,使得所有邊都從前指向後。
複雜度:$O(V + E)$。
做法:反覆取出入度為 0 的節點。如果最終排序長度 ≠ n,代表圖有環。
1 | vector<vector<int>> v(n + 1); // 鄰接表 |
DAG 上最長路徑(拓撲排序 + DP:在拓撲序上做 DP):
1 | dp[1] = 1; // dp[i] = 到達 i 的最長路徑長 |
Kruskal (最小生成樹)
用途:找出連接所有節點的最小權重邊集合。
複雜度:$O(E \log E)$(瓶頸在排序)。
做法:將所有邊按權重排序,依序加入不會形成環的邊(用 DSU 判斷)。
1 | DSU dsu(n); |
LCA (最近公共祖先 - Binary Lifting)
用途:求樹上兩點的最近公共祖先,也可以算兩點距離。
複雜度:預處理 $O(n \log n)$、每次查詢 $O(\log n)$。
做法:up[t][i] = 節點 $t$ 往上跳 $2^i$ 步的祖先。先讓兩點跳到同一深度,再一起往上跳。
1 | vector<vector<int>> v, up; // v = 鄰接表,up = 倍增表 |
用法:
1 | v.resize(n + 1); |
K-th Ancestor(查詢節點 start 的第 k 個祖先):
1 | int x = start; |
Binary Lifting (倍增法 - 通用)
用途:在任意「下一步」函數上做倍增,快速跳 $k$ 步或找到滿足條件的最遠位置。
複雜度:預處理 $O(n \log n)$、每次查詢 $O(\log n)$。
1 | // up[i][j] = 從 j 出發跳 2^i 步到達的位置 |
Bipartite Check (二分圖判定)
用途:判斷圖是否能二著色(即是否為二分圖)。
複雜度:$O(V + E)$。
做法:BFS 染色,相鄰節點必須不同色。若發現衝突則非二分圖。
1 | vector<int> color(n + 1); // 0 = 未染色,1 / 2 = 兩種顏色 |
Cycle Detection (環偵測)
用途:偵測圖中是否存在環,並找出環上的節點。
無向圖找環(DFS,用 parent 陣列回溯路徑):
1 | vector<int> p(n + 1); // p[x] = DFS 中 x 的父節點 |
有向圖找環(DFS + 回溯棧:vis2 記錄「目前正在 DFS 路徑上」的節點):
1 | vector<bool> vis, vis2; // vis = 全域已訪問,vis2 = 當前路徑上 |
Tree Diameter (樹直徑)
用途:找樹上距離最遠的兩點之間的距離。
複雜度:$O(n)$。
做法:從任意點 BFS 找最遠點 u,再從 u BFS 找最遠點 v,u-v 距離即為直徑。
1 | pair<int, int> bfs(int x) { // 回傳 {最遠點, 最遠距離} |
Euler Tour (DFS 序)
用途:把樹壓平成一維陣列,使子樹對應到一段連續區間,搭配 BIT/線段樹做子樹查詢。
複雜度:$O(n)$。
1 | vector<int> in, out; // in[t] = 進入時間戳,out[t] = 離開時間戳 |
Subtree Size (子樹大小)
用途:算每個節點的子樹大小。
複雜度:$O(n)$。
1 | vector<int> vis(n + 1); // vis[t] = t 的子樹中有多少個子孫 |
DSU 離線刪邊 (反向加邊)
用途:需要刪邊的場景,因為 DSU 只支援合併,所以把操作反轉:先刪完再反向加回來。
複雜度:$O(m \cdot \alpha(n))$。
1 | DSU dsu(n); |
動態規劃
0/1 Knapsack (0/1 背包)
用途:$n$ 個物品各有重量和價值,每個最多選一次,求在重量限制 $x$ 內的最大總價值。
複雜度:$O(nx)$。
狀態:$dp[i][j]$ = 考慮前 $i$ 個物品、容量為 $j$ 時的最大價值。
1 | int dp[n + 1][x + 1] = {}; |
空間壓縮版(倒序遍歷確保每個物品只用一次):
1 | vector<int> dp(x + 1); |
可行性背包(判斷哪些總和可達,用 bool 陣列):
1 | vector<bool> dp(100001); |
Unbounded Knapsack (完全背包)
用途:每個物品可以選無限次。
複雜度:$O(nx)$。
差異:正序遍歷($dp[i][j - t]$ 引用同一列,代表可重複選)。
1 | dp[0][0] = 1; |
Coin Change (硬幣問題)
用途:用若干種面額的硬幣湊出目標金額。
方法數(排列:外層遍歷金額,內層遍歷硬幣 → 不同順序算不同方案):
1 | vector<int> dp(k + 1); |
最少硬幣數:
1 | vector<int> dp(k + 1, INF); |
LIS (最長遞增子序列)
用途:找出陣列中最長的嚴格遞增子序列長度。
複雜度:$O(n \log n)$。
做法(patience sort):維護一個遞增陣列 ans,新元素若大於尾端就 append,否則用 lower_bound 替換。
1 | vector<int> ans; // ans[i] = 長度為 i+1 的 LIS 的最小末尾值 |
multiset 版(適合需要求最長非遞增子序列等變體):
1 | multiset<int> ans; |
LCS (最長公共子序列)
用途:找兩個序列的最長公共子序列。
複雜度:$O(nm)$。
狀態:$dp[i][j]$ = $a$ 的前 $i$ 個字元和 $b$ 的前 $j$ 個字元的 LCS 長度。
1 | vector<vector<int>> dp(a.size() + 1, vector<int>(b.size() + 1)); |
回溯路徑(pa 記錄每一步的來源方向:1=左上, 2=上, 3=左):
1 | string ans; |
Edit Distance (編輯距離)
用途:把字串 $a$ 變成字串 $b$ 需要的最少操作數(插入/刪除/替換)。
複雜度:$O(nm)$。
狀態:$dp[i][j]$ = $a$ 的前 $i$ 個字元變成 $b$ 的前 $j$ 個字元的最小編輯距離。
1 | vector<vector<int>> dp(a.size() + 1, vector<int>(b.size() + 1)); |
Grid DP (網格 DP)
路徑計數(從左上到右下,只能往右或往下,'#' 不可走):
複雜度:$O(hw)$。
狀態:$dp[i][j]$ = 走到 $(i, j)$ 的方法數。
1 | int dp[h + 1][w + 1] = {}; |
最大正方形(在 01 矩陣中找最大的全 1 正方形,空間壓縮版):
狀態:$dp[j]$ = 以 $(i, j)$ 為右下角的最大正方形邊長。
1 | vector<int> dp(m + 1); // 上一列的 dp 值 |
Interval DP (區間 DP)
用途:處理「合併/分割區間」類的問題。
複雜度:$O(n^3)$。
狀態:$dp[l][r]$ = 處理區間 $[l, r]$ 的最優解。
合併石頭(每次合併相鄰兩堆,花費 = 兩堆的和,求最小總花費):
1 | vector<vector<int>> dp(n + 1, vector<int>(n + 1, INF / 2)); |
博弈取石頭(兩人輪流從頭或尾取石頭,求先手最大得分):
狀態:$dp[l][r]$ = 在 $[l, r]$ 中先手能拿到的最大分數。
1 | for (int l = n;l >= 1;l--) { |
Bitmask DP (狀態壓縮 DP)
用途:用二進位表示集合的狀態,適合 $n \leq 20$ 的問題。
複雜度:$O(2^n \cdot n)$。
Hamiltonian Path 計數(經過每個節點恰好一次的路徑數):
狀態:$dp[mask][t]$ = 已拜訪集合為 $mask$、目前在節點 $t$ 的路徑數。
1 | vector<vector<int>> dp(1 << n, vector<int>(n)); |
賽局 DP(狀態壓縮博弈:用 bitmask 記錄剩餘可選項目):
1 | vector<int> dp(1 << n, -1); |
Game DP (Nim / SG)
用途:判斷博弈的先手勝負。
狀態:$dp[i]$ = 剩 $i$ 個石頭時,先手是否必勝。
1 | vector<bool> dp(k + 1); // dp[i] = true 表示先手必勝 |
Tree DP (樹 DP)
用途:在樹結構上做 DP,自葉向根合併資訊。
獨立集計數(選出的節點兩兩不相鄰的方案數):
狀態:$dp[0][t]$ = 不選 $t$ 的方案數,$dp[1][t]$ = 選 $t$ 的方案數。
1 | vector<vector<int>> dp; // dp[0][t], dp[1][t] |
DAG 上最長路(記憶化 DFS):
1 | vector<int> dp; |
Weighted Job Scheduling (加權工作排程)
用途:$n$ 個工作各有開始/結束時間和報酬,選出不重疊的工作使總報酬最大。
複雜度:$O(n \log n)$。
狀態:$dp[i]$ = 考慮前 $i$ 個工作的最大報酬。
做法:按結束時間排序,對每個工作二分搜找「開始前最晚結束的工作」。
1 | vector<array<int, 3>> v(n); // {開始, 結束, 報酬} |
貪心
區間排程 (Interval Scheduling)
用途:從一堆區間中選出最多個不重疊的區間。
複雜度:$O(n \log n)$。
策略:按結束時間排序,每次選結束最早且不衝突的區間。
1 | sort(v.begin(), v.end(), [](auto a, auto b) {return a.second < b.second;}); |
多機區間排程 (k-Screen Scheduling)
用途:有 $k$ 個機器(螢幕),每個機器同時只能處理一個區間,求最多能安排幾個。
複雜度:$O(n \log n)$。
策略:按結束時間排序,用 multiset 記錄每個機器目前的結束時間,優先使用「結束時間最接近開始時間」的機器。
1 | sort(v.begin(), v.end(), [](auto a, auto b) {return a.second < b.second;}); |
最小化完成時間 (Task Scheduling)
用途:$n$ 個工作有處理時間和截止時間,排序使得總延遲最小。
複雜度:$O(n \log n)$。
策略:按處理時間排序(SPT rule),讓短的工作先做。
1 | sort(v.begin(), v.end()); // v[i] = {處理時間, 截止時間} |
截止時間排程 - Reverse Sweep (Deadline Job Scheduling)
用途:$n$ 個工作有截止時間和報酬,每天只能做一個工作,求最大總報酬。
複雜度:$O(n \log n)$。
策略:從最後一天開始往前掃,每天從可用工作中選報酬最高的。
1 | vector<vector<int>> v(m + 1); // v[s] = 最早可開始在第 s 天做的工作報酬們 |
截止時間排程 - Forward Sweep (EDF)
用途:$n$ 個工作有開始時間和截止時間,每個時間點做一個,求最多能完成幾個。
複雜度:$O(n \log n)$。
策略:正向模擬時間,用 min-heap 優先處理截止時間最早的。
1 | sort(v.begin(), v.end()); // 按開始時間排序 |
最小費用合併 (Huffman / Min Cost Merge)
用途:每次選兩個合併,費用 = 兩者之和,求最小總費用。經典問題:合併竹棍、Huffman 編碼。
複雜度:$O(n \log n)$。
策略:每次合併最小的兩個(讓大的晚被合併,減少重複計費)。
1 | priority_queue<int, vector<int>, greater<int>> q; // min-heap |
Multiset 貪心配對 - 最大匹配 (Ticket Assignment)
用途:每個需求找一個 $\leq$ 它的最大選項配對。例如:顧客出價 $t$,找 $\leq t$ 的最貴門票。
複雜度:$O(n \log n)$。
1 | multiset<int> st; |
Multiset 貪心配對 - 最小費用 (Min Cost Matching)
用途:每個需求找一個 $\geq$ 它的最小選項配對,使總費用最小。
複雜度:$O(n \log n)$。
1 | multiset<int> st; |
遞增陣列 (Increasing Array)
用途:把陣列變成非遞減的最小代價(只能增加元素值)。
複雜度:$O(n)$。
策略:遇到比前一個小的就補到跟前一個一樣大。
1 | int ans = 0; |
集合等分 (Set Partition)
用途:把 $1 \sim n$ 分成兩個總和相等的集合。
複雜度:$O(n)$。
策略:從大到小,能放就放(先填目標總和小的那邊)。
1 | int cnt = (n * (n + 1)) / 4; // 每個集合的目標總和 |
間隔覆蓋 (Minimum Intervals to Cover Range)
用途:用最少的區間覆蓋一段指定範圍 $[\text{start}, \text{finish}]$。
複雜度:$O(n \log n)$。
策略:排序後,每次從所有起點 <= 當前位置的區間中,選終點最遠的。
1 | sort(v.begin(), v.end()); // 按起點排序 |
間距最小化 (Gap Minimization)
用途:$m$ 個點分成 $n$ 組連續的,使組內總距離最小。等同於刪除 $n-1$ 個最大的間距。
複雜度:$O(m \log m)$。
策略:排序、算相鄰間距、取最小的 $m-n$ 個間距。
1 | sort(x.begin(), x.end()); |
PQ 貪心移除 (Priority Queue Greedy Removal)
用途:依序移除代價最小的元素,移除時更新鄰居的代價。
複雜度:$O((V + E) \log V)$。
策略:用 min-heap 存 {代價, 節點},移除後更新鄰居並重新入堆(懶刪除)。
1 | priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; |
掃描線 (Sweep Line)
用途:求最大重疊區間數(同時進行的事件數上限)。
複雜度:$O(n \log n)$。
策略:把區間拆成 $+1$(開始)和 $-1$(結束)事件,排序後掃描。
1 | vector<pair<int, int>> v(2 * n); // {時間點, +1 或 -1} |
滑動中位數 (Sliding Median)
用途:在滑動視窗中即時查詢中位數。
複雜度:每次插入/刪除 $O(\log n)$。
策略:用兩個 multiset,a 存較小的一半,b 存較大的一半,保持 a 多一個。
1 | multiset<int> a, b; // a: 較小的一半,b: 較大的一半 |
另見「搜尋與排序」中的排序配對 (Ferris Wheel) 和排序匹配 (Apartments),也屬於貪心。
搜尋與排序
Binary Search (二分搜)
用途:在單調性上找分界點。
複雜度:$O(\log n)$。
1 | int l = 0, r = 1e18, ans; |
Ternary Search (三分搜)
用途:在單峰/單谷函數上找極值。
複雜度:$O(\log n)$。
凸函數找最小值:
1 | int l = lo, r = hi; |
Two Pointers / Sliding Window (雙指標 / 滑動視窗)
用途:利用兩個指標在排序陣列或子陣列上高效搜尋。
複雜度:$O(n)$ 或 $O(n^2)$(含外層迴圈)。
三數之和(排序後固定一個,剩下兩個用雙指標搜尋):
1 | sort(v.begin(), v.end()); |
最長不重複子陣列(維護視窗內每個元素出現次數):
1 | map<int, int> mp; // 元素出現次數 |
至多 k 種不同元素的子陣列計數:
1 | map<int, int> mp; |
排序後配對(Ferris Wheel:兩人一組,總重 <= x,求最少組數):
1 | sort(v.begin(), v.end()); |
排序後匹配(Apartments:a 和 b 差在 k 以內就算匹配,求最多配對數):
1 | sort(a.begin(), a.end()); |
Meet in the Middle (折半搜尋)
用途:把 $O(2^n)$ 的暴力拆成兩個 $O(2^{n/2})$,再合併。
複雜度:$O(2^{n/2})$。
例:找子集和等於 $k$ 的方案數。
1 | // 前半部分:枚舉前 n/2 個元素的所有子集 |
Merge Sort - Inversion Count (逆序對計數)
用途:計算陣列中有多少對 $(i, j)$ 滿足 $i < j$ 且 $v[i] > v[j]$。
複雜度:$O(n \log n)$。
做法:在 merge sort 合併時,右半的元素比左半先被放入 → 代表左半剩餘的都比它大。
1 | vector<int> v, a; // v = 原陣列,a = 暫存 |
BIT 版逆序對(用離散化 + BIT 計算每個元素前面有多少比它大的):
1 | BIT bit(n); |
數學
Fast Exponentiation (快速冪)
用途:計算 $a^b \bmod m$。
複雜度:$O(\log b)$。
1 | long long ans = 1; |
Sieve of Eratosthenes (埃氏篩)
用途:找出某範圍內的所有質數。
區間篩(找 $[L, R]$ 中的質數,只需篩到 $\sqrt{R}$):
1 | vector<bool> not_prime(R - L + 1); |
Factorial Trailing Zeros (階乘尾零)
用途:計算 $n!$ 末尾有幾個 $0$(即 $n!$ 中因子 $5$ 的個數)。
複雜度:$O(\log n)$。
1 | int f(int n) { |
Kadane's Algorithm (最大子陣列和)
用途:找出連續子陣列的最大和。
複雜度:$O(n)$。
1 | int ans = -1e18, now = 0; // now = 以當前位置結尾的最大子陣列和 |
前綴和
1D Prefix Sum (一維前綴和)
用途:$O(1)$ 回答區間和查詢。
複雜度:建表 $O(n)$、查詢 $O(1)$。
1 | vector<int> pre(n + 1); // pre[i] = a[1] + a[2] + ... + a[i] |
子陣列和等於 x 的計數(前綴和 + hash map:找有多少個 pre[j] = pre[i] - x):
1 | map<long long, int> mp; // mp[s] = 前綴和為 s 的出現次數 |
2D Prefix Sum (二維前綴和)
用途:$O(1)$ 回答矩形區域和查詢。
複雜度:建表 $O(n^2)$、查詢 $O(1)$。
使用排容原理:sum(x1,y1,x2,y2) = pre[x2][y2] - pre[x1-1][y2] - pre[x2][y1-1] + pre[x1-1][y1-1]。
1 | int a[n + 2][n + 2] = {}; |
3D Prefix Sum (三維前綴和)
用途:$O(1)$ 回答三維長方體區域和查詢。
複雜度:建表 $O(n^3)$、查詢 $O(1)$。
排容原理的三維版本(3 個面 - 3 條邊 + 1 個頂點):
1 | int s[N][N][N] = {}; |
其他技巧
Permutation (排列枚舉)
用途:枚舉字串/陣列的所有排列。
複雜度:$O(n! \times n)$。
1 | string s; |
Gray Code (格雷碼)
用途:產生 n 位元的格雷碼序列(相鄰兩個只差一位元)。
複雜度:$O(2^n)$。
做法:n 位元格雷碼 = 前半加 "0" 前綴,後半為 n-1 位的反轉加 "1" 前綴。
1 | vector<string> f(int n) { |
Fast Hash (防 hack 雜湊)
用途:替 unordered_map 加上隨機化 hash,防止被特殊測資卡 hash 碰撞。
1 | struct FastHash { |
四數之和 (Hash)
用途:在陣列中找四個數和為 x。
複雜度:$O(n^2)$。
做法:枚舉兩兩配對,用 hash map 存前面的配對和。
1 | unordered_map<int, pair<int, int>> mp; // mp[sum] = {i, j} 表示 v[i]+v[j] = sum |
Josephus Problem (約瑟夫問題)
用途:n 人圍一圈,每隔一人淘汰,求淘汰順序。
複雜度:$O(n \log n)$(用 set)。
1 | set<int> st; |
Pragma 加速
用途:在 judge 允許的情況下,讓 GCC 做更激進的優化。
1 |
說些什麼吧!