# CP Template - [IO , PBDS](#IO,PBDS) - [KMP](#KMP) - [DAG](#DAG) - [segmentTree](#SegmentTree) - [ConvexHull](#ConvexHull) - [MinSwaps](#MinSwaps) - [Eratosthenes](#Eratosthenes) - [3DLCS](#3DLCS) - [EditDistance](#EditDistance) - [LCS](#LCS) - [LIS](#LIS) - [Dijkstra](#Dijkstra) - [*A](#*A) - [Maximum s-t Flow](#MaximumS-tFlow) - [BCC](#BCC) - [LCA](#LCA) - [Tarjan](#Tarjan) - [BIT](#BIT) - [擴展歐幾里德](#擴展歐幾里德) - [Bellman Ford](#BellmanFord) - [Hash](#hash) - [ODT](#ODT) (又名科朵莉樹) - [李超線段數](#李超線段數) - [AC自動機](#AC自動機) ## - 重構大綱 - LCS , LIS , EditDistance , Dijkstra , bellman ford 、 KMP 等算法屬於簡單DP不該存於模板內 - 基礎IO背起來 - minSwaps O(n) 版本基本上完全用不到 - RMQ有莫隊算法的版本 - ODT、李超、AC automata、*A 都用不太到 - segmentTree(包括 lazy tag 和 persistent) 、 Hash 、 Eratosthenes 等級的code需要立即寫出來 也不該存於模板中 - BCC LCA 都可以用 Tarjan 改 - Maximum Flow 準備一個 Dinic 即可 - 學一下 NIM - 3D LCS的時間複雜度須為 O(mn) - 新增條目 LCIS ## IO,PBDS ```cpp= #include <bits/stdc++.h> #pragma GCC optimize("O3","unroll-loops") #define IO cin.tie(0), ios::sync_with_stdio(0) #define All(x) x.begin(), x.end() #define sz(x) (int)(x).size() #define sort_unique(x) sort(All(x)); x.erase(unique(All(x)), x.end()); #define eb emplace_back #define pb push_back #define ne nth_element #define lb lower_bound #define ub upper_bound using namespace std; typedef long long ll; typedef pair<ll, ll> pii; typedef vector<ll> vl; // #include <ext/pb_ds/assoc_container.hpp> // #include <ext/pb_ds/tree_policy.hpp> // using namespace __gnu_pbds; // #define multiset tree<ll, null_type,less_equal<ll>, rb_tree_tag,tree_order_statistics_node_update> /** order_of_key(k) : nums strictly smaller than k find_by_order(k): index from 0 **/ const int N = 50+5; const ll INF = 1e9; const int mod = 1e9+2e5+7; const ll MXP = 1e10; const int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; ``` ## KMP ```cpp= bool match(string &s, string &t, vector<int> &F) { for (int i = 0, pos = -1 ; i < s.size() ; i++) { while (~pos && s[i] != t[pos + 1]) pos = F[pos]; if (s[i] == t[pos + 1]) pos++; if (pos + 1 == (int)t.size()) return true; } return false; } ``` ## DAG ```cpp= void DFS(map<int,queue<int>> &graph , map<int,bool> &visited , int place , stack<int> &ans){ if(visited[place] == true) return; visited[place]=true; while(!graph[place].empty()) DFS(graph, visited, graph[place].front() , ans) , graph[place].pop() ; ans.push(place); } for(auto&n:graph) DFS(graph , visited , n.first , ans) ; while(!ans.empty()) cout << ans.top() << " " , ans.pop(); ``` ## SegmentTree ```cpp= #define Ls(x) x << 1 #define Rs(x) x << 1 | 1 typedef long long ll; int N = 1e5+5; vector<int> segTree(4*N), lazy(4*N) , arr(N); // segment tree with lazy propagation int sol(int l, int r){ return segTree[l] + segTree[r]; } void build(int l, int r, int idx = 1){ if(l == r){ segTree[idx] = arr[l]; return; } int mid = (l+r) >> 1; build(l, mid, Ls(idx)); build(mid+1, r, Rs(idx)); segTree[idx] = sol(Ls(idx), Rs(idx)); } void pushDown(int l, int r, int idx){ if(lazy[idx] == 0) return; // adding lazy[idx] to each element in range [l, r] segTree[idx] += (r-l+1)*lazy[idx]; // set lazy for children if(l != r) lazy[Ls(idx)] += lazy[idx],lazy[Rs(idx)] += lazy[idx]; // clear lazy[idx] lazy[idx] = 0; } void update(int l, int r, int ql, int qr, int val, int idx = 1){ // l : left index of current range // r : right index of current range // ql : left index of query range // qr : right index of query range // val : value to be added to each element in range [ql, qr] // idx : current index of segment tree pushDown(l, r, idx); // push down lazy value to children if(l > qr || r < ql) return; // out of range // completely in range case // if current range is not completely in range, we need to update its children if(l >= ql && r <= qr){ segTree[idx] += (r-l+1)*val; if(l != r) lazy[Ls(idx)] += val, lazy[Rs(idx)] += val; return; } int mid = (l+r) >> 1; update(l, mid, ql, qr, val, Ls(idx)); // update left child update(mid+1, r, ql, qr, val, Rs(idx)); // update right child segTree[idx] = sol(Ls(idx), Rs(idx)); } int query(int l, int r, int ql, int qr, int idx = 1){ pushDown(l, r, idx); // push down lazy value to children if(l > qr || r < ql) return 0; // out of range if(l >= ql && r <= qr) return segTree[idx]; // completely in range int mid = (l+r) >> 1; return sol(query(l, mid, ql, qr, Ls(idx)), query(mid+1, r, ql, qr, Rs(idx))); // query left child and right child } ``` ## ConvexHull ```cpp= void Dhull(vector<pii> points , vector<pii> &hull){ hull.push_back(points[0]) , hull.push_back(points[1]); for(int i = 2 ; i < points.size() ; i++){ while(hull.size() >= 2){ pair<int,int> p1 = hull[hull.size()-2] , p2 = hull[hull.size()-1] , p3 = points[i]; int x1 = p2.first - p1.first , y1 = p2.second - p1.second; int x2 = p3.first - p2.first , y2 = p3.second - p2.second; if(x1*y2 - x2*y1 <= 0) break; hull.pop_back(); } hull.push_back(points[i]); } } int main(){ IO ; vector<pair<int,int>> points,hull; int n , x , y; cin >> n ; for(int i = 0 ; i < n ; i++) cin>>x>>y , points.pb({x,y}); sort(points.begin() , points.end()); Dhull(points,hull) ; reverse(points.begin(),points.end()); Dhull(points,hull) ; for(auto p : hull) cout << p.first << " " << p.second << endl; } ``` ## MinSwaps ```cpp= int minSwaps(vector<int> &arr, int n) { pii arrPos[n]; for (int i = 0; i < n; i++) { arrPos[i].first = arr[i]; arrPos[i].second = i; } sort(arrPos, arrPos + n); vector<bool> vis(n, false); int ans = 0; for (int i = 0; i < n; i++) { if (vis[i] or arrPos[i].second == i) continue; int cycle_size = 0 , j = i ; while (!vis[j]){ vis[j] = 1; j = arrPos[j].second; cycle_size++; } if(cycle_size > 0) ans += (cycle_size - 1); } return ans; } ``` ## Eratosthenes ```cpp= auto eratosthenes(int upperbound) { vector<bool> flag(upperbound + 1, true); flag[0] = flag[1] = false; for (int i = 2; i * i <= upperbound; ++i) { if (flag[i]) { for (int j = i * i; j <= upperbound; j += i) flag[j] = false; } } return flag; } ``` ## 3DLCS (此條目需更新) ```cpp= #include <bits/stdc++.h> using namespace std; int main(){ string x,y,z ; cin >> x >> y >> z ; cout << lcsOf3(x,y,z , x.size() , y.size() , z.size()) << endl; } int lcsOf3( string X, string Y, string Z, int m, int n, int o){ int L[m+1][n+1][o+1]; for (int i=0; i<=m; i++){ for (int j=0; j<=n; j++){ for (int k=0; k<=o; k++){ if (i == 0 || j == 0||k==0) L[i][j][k] = 0; else if (X[i-1] == Y[j-1] && X[i-1]==Z[k-1]) L[i][j][k] = L[i-1][j-1][k-1] + 1; else L[i][j][k] = max(max(L[i-1][j][k],L[i][j-1][k]),L[i][j][k-1]); } } } return L[m][n][o]; } ``` ## EditDistance ```cpp= int EditDistance2(string s1 , string s2){ // space complexity : O(n) vector<int> EditDistance(s2.size()+1, 0); for(int i = 0 ; i <= s2.size() ; i++) EditDistance[i] = i; for(int i = 1 ; i <= s1.size() ; i++){ int prev = EditDistance[0]; EditDistance[0] = i; for(int j = 1 ; j <= s2.size() ; j++){ int temp = EditDistance[j]; if(s1[i-1] == s2[j-1]) EditDistance[j] = prev; else EditDistance[j] = min(prev , min(EditDistance[j] , EditDistance[j-1])) + 1; prev = temp; } } return EditDistance[s2.size()]; } ``` ## LCS ## LIS ## Dijkstra ## *A ## MaximumS-tFlow ## BCC ## LCA ## Tarjan