0% found this document useful (0 votes)
117 views

C++ Competitive Programming Codebook

The document discusses various algorithms and data structures used in computational problems. It covers topics such as discretization, the Chinese remainder theorem, dynamic programming techniques like knapsack and longest common subsequence, tree algorithms like minimum spanning trees and lowest common ancestors, flow algorithms, graph algorithms, mathematical topics, computational geometry concepts, and string matching methods. The document provides an overview of the basic templates and implementations for these common algorithms and data structures.

Uploaded by

Donburi Sharker
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
117 views

C++ Competitive Programming Codebook

The document discusses various algorithms and data structures used in computational problems. It covers topics such as discretization, the Chinese remainder theorem, dynamic programming techniques like knapsack and longest common subsequence, tree algorithms like minimum spanning trees and lowest common ancestors, flow algorithms, graph algorithms, mathematical topics, computational geometry concepts, and string matching methods. The document provides an overview of the basic templates and implementations for these common algorithms and data structures.

Uploaded by

Donburi Sharker
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

NTNU_import_magic 1

Contents 1 Basic
1 Basic 1 1.1 default template
1.1 default template . . . . . . . . . . . . . . . . . . . 1

2 Implementation 1 1 #include <bits/stdc++.h>


2.1 Discretization . . . . . . . . . . . . . . . . . . . . 1 2 #define inf 0x3f3f3f3f
2.2 蔡勒公式 . . . . . . . . . . . . . . . . . . . . . . . . 1
2.3 約瑟夫問題 . . . . . . . . . . . . . . . . . . . . . . . 1
3 #define dinf 0xc0c0c0c0
4 #define jizz ios::sync_with_stdio(0), cin.tie(0)
3 Dynamic Programming 2 5 #define EB emplace_back
3.1 0/1 &無限背包 . . . . . . . . . . . . . . . . . . . . . 2 6 #define MP make_pair
3.2 有限背包 . . . . . . . . . . . . . . . . . . . . . . . . 2
3.3 經典零錢問題 . . . . . . . . . . . . . . . . . . . . . . 2 7 #define X first
3.4 LIS . . . . . . . . . . . . . . . . . . . . . . . . . . 2 8 #define Y second
3.5 LCS . . . . . . . . . . . . . . . . . . . . . . . . . . 2 9 using namespace std;
3.6 TSP . . . . . . . . . . . . . . . . . . . . . . . . . . 2 10 using ll = long long;
11 using llu = long long unsigned;
4 Tree 3
4.1 MST . . . . . . . . . . . . . . . . . . . . . . . . . . 3 12 using pii = pair<int, int>;
4.1.1 Kruskal . . . . . . . . . . . . . . . . . . . . . 3
4.1.2 prim . . . . . . . . . . . . . . . . . . . . . . 3
4.2 LCA . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2 Implementation
5 Flow 3
5.1 BCC_Tarjan . . . . . . . . . . . . . . . . . . . . . . 3 2.1 Discretization
6 Graph Theory 4
6.1 Dijkstra’s . . . . . . . . . . . . . . . . . . . . . . 4 1 vector<int> status,lisan;
6.2 Bellman‐Ford . . . . . . . . . . . . . . . . . . . . . 4
6.3 Floyd‐Warshall . . . . . . . . . . . . . . . . . . . . 4 2 inline vector<int> discretization(vector<int> a){
6.4 SPFA . . . . . . . . . . . . . . . . . . . . . . . . . 4 3 // 離 散 化 、 不 影 響 原 先 位 置
6.5 二分圖匹配 . . . . . . . . . . . . . . . . . . . . . . . 4 4 status.resize(a.size());
7 Math 4 5 lisan = a;
7.1 Gcd/Lcm . . . . . . . . . . . . . . . . . . . . . . . . 4 6 sort(lisan.begin(),lisan.end());
7.2 ExGcd/ModInverse . . . . . . . . . . . . . . . . . . . 4 7 lisan.resize(unique(lisan.begin(),lisan.end())-
7.3 CRT . . . . . . . . . . . . . . . . . . . . . . . . . . 5
7.4 費馬小定理 . . . . . . . . . . . . . . . . . . . . . . . 5 lisan.begin());
7.5 Long Long Primes . . . . . . . . . . . . . . . . . . . 5 8 for(int i = 0; i < (int)a.size(); i++)
7.6 Merge Sort (逆序數對) . . . . . . . . . . . . . . . . . 5 9 status[i] = lower_bound(lisan.begin(),lisan.
8 Computational Geometry 5 end(),a[i])-lisan.begin();
8.1 Basic Vector . . . . . . . . . . . . . . . . . . . . . 5 10 return status;
8.2 Rotating Calipers . . . . . . . . . . . . . . . . . . . 5 11 }
8.3 Shortest Point Pair . . . . . . . . . . . . . . . . . . 6
8.4 Convex_Andrew_Monotone . . . . . . . . . . . . . . . . 6 12 inline vector<int> model(vector<int> a){
13 // vector 去 掉 重 複 並 排 序
9 Data Structure 6 14 lisan = a;
9.1 BIT . . . . . . . . . . . . . . . . . . . . . . . . . . 6
9.2 HLD LCA . . . . . . . . . . . . . . . . . . . . . . . . 6 15 sort(lisan.begin(),lisan.end());
9.3 HLD . . . . . . . . . . . . . . . . . . . . . . . . . . 6 16 lisan.resize(unique(lisan.begin(),lisan.end())-
9.4 Disjoint Set . . . . . . . . . . . . . . . . . . . . . 7 lisan.begin());
9.5 Segment Tree . . . . . . . . . . . . . . . . . . . . . 7
17 return lisan;
9.6 Treap . . . . . . . . . . . . . . . . . . . . . . . . . 7
18 }
10 String 7
10.1Manacher . . . . . . . . . . . . . . . . . . . . . . . 7
10.2 Failure Function/KMP . . . . . . . . . . . . . . . . . 8
10.3 Rolling Hash/KMP . . . . . . . . . . . . . . . . . . . 8
2.2 蔡勒公式

1 int ReturnWeekDay(unsigned int iYear, unsigned int


iMonth, unsigned int iDay) {
2 int iWeek = 0;
3 unsigned int y = 0, c = 0, m = 0, d = 0;
4 if(iMonth == 1 || iMonth == 2) {
5 c = ( iYear - 1 ) / 100;
6 y = ( iYear - 1 ) % 100;
7 m = iMonth + 12;
8 d = iDay;
9 }
10 else {
11 c = iYear / 100;
12 y = iYear % 100;
13 m = iMonth;
14 d = iDay;
15 }
16 iWeek = y + y / 4 + c / 4 - 2 * c + 26 * (m + 1) /
10 + d - 1;
17 iWeek = iWeek >= 0 ? (iWeek % 7) : (iWeek % 7 + 7)
;
18 if(iWeek == 0) iWeek = 7;
19 return iWeek;
20 }

2.3 約瑟夫問題
NTNU_import_magic 2
1 /// n 個 人 , 查 m 個 數 5 for (int i=0; i<N; i++) length[i] = 1;
2 int JosephusProblem(int n, int m) { 6 for (int i=0; i<N; i++)
3 if(n<1 || m<1) return -1; 7 for (int j=0; j<i; j++)
4 vector<int> f(n+1, 0); 8 if (s[j] < s[i])
5 for(unsigned i=2; i<=n; ++i) 9 length[i] = max(length[i], length[j] +
6 f[i] = (f[i-1]+m) % i; 1);
7 return f[n]; 10 int l = 0;
8 } 11 for (int i=0; i<N; i++) l = max(l, length[i]);
12 return l;
13 }
3 Dynamic Programming 14 // Robinson-Schensted-Knuth Algorithm
15 int LIS(vector<int>& s) {
3.1 0/1 &無限背包 16 if (s.size() == 0) return 0;
17 vector<int> v;
1 const int N = 100, W = 100000; 18 v.push_back(s[0]);
2 int cost[N], weight[N], c[W + 1]; 19 for (int i=1; i<s.size(); ++i) {
3 void knapsack(int n, int w) { 20 int n = s[i];
4 memset(c, 0, sizeof(c)); 21 if (n > v.back()) v.push_back(n);
5 for (int i = 0; i < n; ++i) 22 else *lower_bound(v.begin(), v.end(), n) = n;
6 for (int j = w; j - weight[i] >= 0; --j) // 23 }
0/1 背 包 24 return v.size();
7 // for (int j = weight[i]; j <= w; ++j) 無 限 背 25 }

8 c[j] = max(c[j], c[j - weight[i]] + cost[i
]); 3.5 LCS
9 cout << "最 高 的 價 值 為" << c[w];
10 } 1 // DP
2 const int N1 = 7, N2 = 5;
3 int s1[N1+1] = {0, 2, 5, 7, 9, 3, 1, 2};
3.2 有限背包 4 int s2[N2+1] = {0, 3, 5, 3, 2, 8};
5 int length[N1+1][N2+1];
1 const int N = 100, W = 100000; 6 int LCS() {
2 int cost[N], weight[N], number[N], c[W + 1]; 7 for (int i=0; i<=N1; i++) length[i][0] = 0;
3 void knapsack(int n, int w) { 8 for (int j=0; j<=N2; j++) length[0][j] = 0;
4 for (int i = 0; i < n; ++i) { 9 for (int i=1; i<=N1; i++)
5 int num = min(number[i], w / weight[i]); 10 for (int j=1; j<=N2; j++)
6 for (int k = 1; num > 0; k *= 2) { 11 if (s1[i] == s2[j]) length[i][j] = length[
7 if (k > num) k = num; i-1][j-1] + 1;
8 num -= k; 12 else length[i][j] = max(length[i-1][j],
9 for (int j = w; j >= weight[i] * k; --j) length[i][j-1]);
10 c[j] = max(c[j], c[j - weight[i] * k] 13 return length[N1][N2];
+ cost[i] * k); 14 }
11 } 15 // Hunt-Szymanski Algorithm
12 } 16 int LCS(string &s1, string &s2) {
13 cout << "最 高 的 價 值 為" << c[w]; 17 vector<int> p[128]; // 假 設 字 元 範 圍 為 0 ~ 127
14 } 18 for (int i = 0; i < s2.size(); ++i)
19 p[s2[i]].push_back(i);
20 vector<int> v;
21 v.push_back(-1);
3.3 經典零錢問題 22 for (int i = 0; i < s1.size(); ++i)
23 for (int j = p[s1[i]].size() - 1; j >= 0; --j)
1 int price[5] = {5, 2, 6, 11, 17}; {
2 bool c[1000+1]; //int c[1000+1]; 24 int n = p[s1[i]][j];
3 void change(int m) { 25 if (n > v.back()) v.push_back(n);
4 memset(c, false, sizeof(c)); 26 else *lower_bound(v.begin(), v.end(), n) =
5 c[0] = true; n;
6 for (int i = 0; i < 5; ++i) 27 }
7 for (int j = price[i]; j <= m; ++j) 28 return v.size() - 1;
8 c[j] ||= c[j-price[i]]; 29 }
9 // c[j] += c[j-price[i]];
10 if (c[m]) cout << "湊 得 到";
11 else cout << "湊 不 到"; 3.6 TSP
12 // cout << "湊 得 價 位" << m;
13 // cout << "湊 法 總 共" << c[m] << "種";
1 #define MAXN 16
14 }
2 int n;/*點 數*/
3 int dp[MAXN][1<<MAXN];/*DP陣 列*/
4 int g[MAXN][MAXN];/*圖*/
3.4 LIS 5 int dfs(int s,int d){
6 if(dp[d][s])return dp[d][s];
1 // DP 7 if((1<<d)==s)return g[0][d];
2 const int N = 100; 8 dp[d][s]=INT_MAX;
3 int s[N], length[N]; 9 for(int i=0;i<n;++i){
4 int LIS() { 10 if(((1<<i)&s)&&i!=d){
NTNU_import_magic 3
11 dp[d][s]=std::min(dp[d][s],dfs(s^(1<<d),i) 4.2 LCA
+g[i][d]);
12 } 1 #define MAXN 100000
13 } 2 #define MAX_LOG 17
14 return dp[d][s]; 3 typedef vector<int >::iterator VIT;
15 } 4 int pa[MAX_LOG + 1][MAXN + 5], dep[MAXN + 5];
5 vector<int >G[MAXN + 5];
6 void dfs(int x, int p) {
4 Tree 7 pa[0][x] = p;
4.1 MST 8 for(int i = 0; i + 1 < MAX_LOG; ++i) {
9 pa[i + 1][x] = pa[i][pa[i][x]];
4.1.1 Kruskal 10 }
11 for(VIT i = G[x].begin(); i != G[x].end(); ++i) {
12 if(*i == p)continue;
1 struct edge {
13 dep[*i] = dep[x] + 1;
2 int u, v, w;
14 dfs(*i, x);
3 bool operator < (const edge &r) const {
4 return w < r.w; 15 }
5 } 16 }
6 }; 17 inline int find_lca(int a, int b) {
7 int vn, en; // vertex num, edge num 18 if(dep[a] > dep[b]) swap(a, b);
8 vector<edge> ve; 19 for(int i = dep[b] - dep[a], k = 0; i; i /= 2) {
9 vector<int> dsu; 20 if(i & 1)b = pa[k][b];
10 int Find(int x) { 21 ++k;
11 if(x == dsu[x]) return x; 22 }
12 return dsu[x] = x; 23 if(a == b)return a;
13 } 24 for(int i = MAX_LOG; i >= 0; --i) {
14 bool Union(int x, int y) { 25 if(pa[i][a] != pa[i][b]) {
15 int a = Find(x), b = Find(y); 26 a = pa[i][a];
16 if(a != b) { 27 b = pa[i][b];
17 dsu[a] = b; 28 }
18 return true; 29 }
19 } 30 return pa[0][a];
20 return false; 31 }
21 }
22 int Kruskal() {
23 for(int i = 0; i < vn; ++i) dsu.push_back(i); 5 Flow
24 sort(ve.begin(), ve.end()); 5.1 BCC_Tarjan
25 int cnt = 0, ans = 0;
26 for(int i = 0; i < en && cnt < vn; ++i) {
27 if(Union(ve[i].u, ve[i].v)) { 1 void dfs(int u,int pa=-1){//u當 前 點 , pa父 親
28 ans += ve[i].w; 2 int v,child=0;
29 ++cnt; 3 low[u]=vis[u]=++Time;
30 } 4 st[top++]=u;
31 } 5 for(size_t i=0;i<G[u].size();++i){
32 return ans; 6 if(!vis[v=G[u][i]]){
33 } 7 dfs(v,u),++child;
8 low[u]=std::min(low[u],low[v]);
9 if(vis[u]<=low[v]){
4.1.2 prim 10 is_cut[u]=1;
11 bcc[++bcc_cnt].clear();
12 int t;
1 struct edge { 13 do{
2 int idx, w;
14 bcc_id[t=st[--top]]=bcc_cnt;
3 bool operator < (const edge &r) const {
15 bcc[bcc_cnt].push_back(t);
4 return w > r.w;
16 }while(t!=v);
5 }
17 bcc_id[u]=bcc_cnt;
6 };
18 bcc[bcc_cnt].push_back(u);
7 int prim() {
8 int vn; // vertex num 19 }
9 vector<edge> adj[vn]; 20 }
10 int ans = 0; 21 else if(vis[v]<vis[u]&&v!=pa)//反 向 邊
11 priority_queue<edge> pq; 22 low[u]=std::min(low[u],vis[v]);
12 vector<bool> vis(vn, false); 23 }
13 vis[0] = true; 24 if(pa==-1&&child<2) is_cut[u]=0;//u是dfs樹 的 根 要 特
14 for(auto v : adj[0]) pq.emplace(v); 判
15 while(!pq.empty()) { 25 }
16 edge mn = pq.top(); 26 inline void bcc_init(int n){
17 pq.pop(); 27 Time=bcc_cnt=top=0;
18 if(vis[mn.idx]) continue; 28 for(int i=1;i<=n;++i){
19 vis[mn.idx] = true; 29 G[i].clear();
20 ans += mn.w; 30 vis[i]=0;
21 for(auto v : adj[mn.idx]) pq.emplace(v); 31 is_cut[i]=0;
22 } 32 bcc_id[i]=0;
23 } 33 }
34 }
NTNU_import_magic 4

6 Graph Theory 6.4 SPFA


6.1 Dijkstra’s 1 void spfa(int s){
2 fill(dist,dist+vn,INF); dist[s]=0;
1 int vn; // vertex num 3 vector<int> cnt(vn,0); vector<bool> inq(vn,0);
2 struct Edge { 4 queue<int> q; q.push(s); inq[s]=true;
3 int idx, w; 5 while(!q.empty()){
4 bool operator < (const Edge &r) const { 6 int u=q.front(); q.pop();
5 return w > r.w; 7 inq[u]=false;
6 } 8 for(auto v:adj[u]){
7 }; 9 if(dist[v.idx]>dist[u]+v.w){
8 vector<Edge> adj[maxv]; 10 if(++cnt[v.idx]>=vn) return true;
9 void dijkstra(int s) { 11 dist[v.idx]=dist[u]+v.w;
10 vector<bool> vis(vn, false); 12 if(!inq[v.idx]) inq[v.idx]=true, q.
11 vector<int> dist(vn, INF); push(v.idx);
12 dist[s] = 0; 13 }
13 priority_queue<Edge> pq; 14
14 pq.emplace(0, s); 15 }
15 while(!pq.empty()) { 16 }
16 int u = pq.top().idx; 17 }
17 pq.pop();
18 if(vis[u]) continue;
vis[u] = true;
19
6.5 二分圖匹配
20 for(auto v : adj[u]) {
21 if(dist[v.idx] > dist[u] + v.w) {
22 dist[v.idx] = dist[u] + v.w; 1 // 最 大 獨 立 集=所 有 頂 點 數 -最 小 頂 點 覆 蓋
23 pq.emplace(dist[v.idx], v.idx); 2 int nx, ny; // X的 點 數 目 、 Y的 點 數 目
24 } 3 int mx[100], my[100]; // X各 點 的 配 對 對 象 、 Y各 點 的 配
25 } 對對象
26 } 4 bool vy[100]; // 記 錄Graph Traversal拜 訪 過 的
27 } 點
5 bool adj[100][100];
6 bool DFS(int x){
7 for (int y=0; y<ny; ++y)
6.2 Bellman‐Ford 8 if (adj[x][y] && !vy[y]){
9 vy[y] = true;
1 int vn; // vertex num 10 if (my[y] == -1 || DFS(my[y])){
2 struct Edge { 11 mx[x] = y; my[y] = x;
3 int idx, w; 12 return true;
4 }; 13 }
5 vector<Edge> adj[maxv]; 14 }
6 bool bellmanford(int s) { //return true if negative 15 return false;
cycle exists; 16 }
7 int cnt = 0; 17 int bipartite_matching(){
8 bool update = false; 18 memset(mx, -1, sizeof(mx));
9 vector<int> dist(vn, INF); 19 memset(my, -1, sizeof(my));
10 dist[s] = 0; 20 int c = 0;
11 do { 21 for (int x=0; x<nx; ++x){
12 if(++cnt == vn) return true; 22 memset(vy, false, sizeof(vy));
13 update = false; 23 if (DFS(i)) c++;
14 for(int u = 0; u < vn; ++u) { 24 }
15 if(dist[u] == INF) continue; 25 return c;
16 for(auto v : adj[u]) { 26 }
17 if(dist[v.idx] > dist[u] + v.w) {
18 update = true;
19 dist[v.idx] = dist[u] + v.w; 7 Math
20 } 7.1 Gcd/Lcm
21 }
22 }
1 int gcd(int a, int b) {
23 } while(update);
2 if(b == 0) return a;
24 return false;
3 return gcd(b, a % b);
25 }
4 }
5
6 int lcm(int a, int b) {
6.3 Floyd‐Warshall 7 return a / gcd(a, b) * b;
8 }
1 int dist[MAX_V][MAX_V];
2 for(int k = 0; k < vn; ++k)
3 for(int i = 0; i < vn; ++i) 7.2 ExGcd/ModInverse
4 for(int j = 0; j < vn; ++j)
5 dist[i][j] = min(dist[i][j], dist[i][k] + 1 int exgcd(int a, int b, int &x, int &y) {
dist[k][j]); 2 if(b == 0) {
3 x = 1;
NTNU_import_magic 5
4 y = 0; 15 else{
5 return a; 16 tmp[i++] = right[ri++];
6 } 17 flag++;
7 int r = exgcd(b, a % b, x, y); 18 }
8 int t = x; 19 }
9 x = y; 20 while(li < llen){
10 y = t - a / b * y; 21 tmp[i++] = left[li++];
11 return r; 22 ret += flag;
12 } 23 }
13 int modInverse(int n, int P) { 24 while(ri < rlen){
14 int x, y;
25 tmp[i++] = right[ri++];
15 exgcd(n, P, x, y); 26 // flag++;
16 return (P + x % P) % P; 27 }
17 } 28 memcpy(arr,tmp,sizeof(int)*len);
29 return ret;
30 }
7.3 CRT
8 Computational Geometry
1 int CRT(int a[], int m[], int n) {
2 int M = 1, ans = 0; 8.1 Basic Vector
3 for(int i = 1; i <= n; ++i) M *= m[i];
4 for(int i = 1; i <= n; ++i) { 1 template<typename T>
5 int x, y; 2 struct point{
6 int Mi = M / m[i]; 3 T x,y;
7 exgcd(Mi, m[i], x, y); 4 point(){}
8 ans = (ans + Mi * x * a[i]) % M; 5 point(const T&x,const T&y):x(x),y(y){}
9 } 6 point operator+(const point &b)const{
10 if(ans < 0) ans += M; 7 return point(x+b.x,y+b.y);
11 return ans; 8 }
12 } 9 point operator-(const point &b)const{
10 return point(x-b.x,y-b.y);
11 }
7.4 費馬小定理 12 point operator*(const T &b)const{
13 return point(x*b,y*b);
1 LL pow(LL a,LL p,LL mod){ 14 }
2 if(a%mod==0) return 0; 15 point operator/(const T &b)const{
3 LL ret=1ll%mod; 16 return point(x/b,y/b);
4 for(LL cur=a;p;cur=cur*cur%mod,p>>=1) 17 }
5 if(p&1ll) 18 bool operator==(const point &b)const{
6 ret=ret*cur%mod; 19 return x==b.x&&y==b.y;
7 return ret; 20 }
8 } 21 T dot(const point &b)const{
9 int main(){ 22 return x*b.x+y*b.y;
10 const LL prime=11; 23 }
11 for(LL a=1, inva;a<prime;++a){ 24 T cross(const point &b)const{
12 inva=pow(a,prime-2,prime); 25 return x*b.y-y*b.x;
13 printf("a=%2lld, a^1=a^(p-2)=%2lld,a*a^(p-2)=% 26 }
lld\n",a,inva,a*inva%prime); 27 T abs2()const{//向 量 長 度 的 平 方
14 } 28 return dot(*this);
15 } 29 }
30 };

7.5 Long Long Primes 8.2 Rotating Calipers


1 long long rotatingClaiper(vector<PT> p){ //計 算 最 遠 點
對距離的平方
7.6 Merge Sort (逆序數對) 2 int n=p.size(), t=1;
3 long long ans=0;
1 #define MAX 100000 4 p.push_back(p[0]);
2 int tmp[MAX]; 5 for(int i=0;i<n;i++){
3 long long mergeSort(int *arr, unsigned len){ 6 PT now=p[i+1]-p[i]; //當 前 這 條 線 的 方 向 向 量
4 if(len <= 1) return 0; 7 //找 出 距 離 邊 (p[i],p[i+1]) 最 遠 的 點 p[t]
5 unsigned llen = len /2, rlen = len - llen; 8 while( now.cross(p[t+1]-p[i]) > now.cross(p[t
6 int *left = arr, *right = arr+llen; ]-p[i]) ) t=(t+1)%n;
7 long long ret = mergeSort(left,llen) + mergeSort( 9 ans = max(ans, max((p[i]-p[t]).abs2(), (p[i
right, rlen); +1]-p[t+1]).abs2()));
8 unsigned li=0,ri=0,i=0; 10 //其 實 可 以 簡 化 成 : ans = max(ans, (p[i]-p[t]).
9 long long flag=0; abs2() );
10 while(li < llen && ri < rlen){ 11 //想 一 想 為 什 麼?!
11 if(left[li] <= right[ri]){ 12 }
12 tmp[i++] = left[li++]; 13 return ans;
13 ret += flag; 14 }
14 }
NTNU_import_magic 6
8.3 Shortest Point Pair 1 #define lowbit(x) (x&-x)
2 int bit[MAXN],n;
3 void modify(int x,int d){
1 struct Point {float x, y;} p[10], t[10];
4 // A[x] += d
2 bool cmpx(Point i, Point j) {return i.x < j.x;}
5 for(;x<=n;x+=lowbit(x)) bit[x] += d;
3 bool cmpy(Point i, Point j) {return i.y < j.y;}
6 }
4 float DnC(int L, int R){
7 long long query(int x){
5 if (L >= R) return 1e9;
8 // 查 詢[1~x]的 總 和
6 int M = (L + R) / 2;
9 long long sum=0;
7 float d = min(DnC(L,M), DnC(M+1,R));
10 for(;x;x-=lowbit(x)) sum += bit[x];
8 int N = 0;
11 return sum;
9 for (int i=M; i>=L && p[M].x - p[i].x < d; --i)
12 }
t[N++] = p[i];
10 for (int i=M+1; i<=R && p[i].x - p[M].x < d; ++i)
t[N++] = p[i];
11 sort(t, t+N, cmpy); 9.2 HLD LCA
12 for (int i=0; i<N-1; ++i)
13 for (int j=1; j<=3 && i+j<N; ++j) 1 inline void build_link(int root,int n){
14 d = min(d, distance(t[i], t[i+j])); 2 pa[root]=-1;
15 return d; 3 for(int i=1;i<=n;++i){/*假 設 節 點 編 號 是1~n*/
16 } 4 if(~pa[i]&&max_son[pa[i]]==i)continue;
17 float closest_pair(){ 5 for(int j=i;j!=-1;j=max_son[j])link_top[j]=i;
18 sort(p, p+10, cmpx); 6 }
19 return DnC(0, N-1); 7 }
20 } 8 inline int find_lca(int a,int b){
9 while(link_top[a]!=link_top[b]){
10 if(dep[link_top[a]]>dep[link_top[b]])a=pa[
8.4 Convex_Andrew_Monotone link_top[a]];
11 else b=pa[link_top[b]];
12 }
1 struct vec{
13 return dep[a]<dep[b]?a:b;
2 int x,y;
14 }
3 vec operator-(vec a){return vec{x-a.x,y-a.y};}
4 int cross(vec a){return x*a.y-y*a.x;}
5 };
6 bool comp(const vec &a, const vec &b){return a.x < b.x 9.3 HLD
|| (a.x == b.x && a.y < b.y);}
7 vector<vec> &convex(vector<vec> &pt){ 1 #define MAXN 100005
8 sort(pt.begin(),pt.end(),comp); 2 typedef std::vector<int >::iterator VIT;
9 vector<vec> &conv = *(new vector<vec>); 3 int siz[MAXN],max_son[MAXN],pa[MAXN],dep[MAXN];
10 int top=0; 4 /*節 點 大 小 、 節 點 大 小 最 大 的 孩 子 、 父 母 節 點 、 深 度*/
11 for(size_t i=0;i<pt.size();i++){ // lower hull 5 int link_top[MAXN],link[MAXN],cnt;
12 while(top >= 2 && (conv[top-1]-conv[top-2]). 6 /*每 個 點 所 在 鏈 的 鏈 頭 、 樹 鏈 剖 分 的DFS 序 、 時 間 戳*/
cross(pt[i]-conv[top-2]) <= 0){ 7 std::vector<int >G[MAXN];/*用vector存 樹*/
13 conv.pop_back(); 8 void find_max_son(int x){
14 top--; 9 siz[x]=1;
15 } 10 max_son[x]=-1;
16 conv.emplace_back(pt[i]); top++; 11 for(VIT i=G[x].begin();i!=G[x].end();++i){
17 } 12 if(*i==pa[x])continue;
18 for(int i=int(pt.size())-2,t=top+1;i>=0;i--){// 13 pa[*i]=x;
upper hull 14 dep[*i]=dep[x]+1;
19 while(top >= t && (conv[top-1]-conv[top-2]). 15 find_max_son(*i);
cross(pt[i]-conv[top-2]) <= 0){ 16 if(max_son[x]==-1||siz[*i]>siz[max_son[x]])
20 conv.pop_back(); max_son[x]=*i;
21 top--; 17 siz[x]+=siz[*i];
22 } 18 }
23 conv.emplace_back(pt[i]); top++; 19 }
24 } 20 void build_link(int x,int top){
25 if(pt.size()>1){conv.pop_back();} 21 link[x]=++cnt;/*記 錄x點 的 時 間 戳*/
26 return conv;
22 link_top[x]=top;
27 }
23 if(max_son[x]==-1)return;
28 double shoe_lace(vector<vec> &conv){
24 build_link(max_son[x],top);/*優 先 走 訪 最 大 孩 子*/
29 int sum = 0;
25 for(VIT i=G[x].begin();i!=G[x].end();++i){
30 int sz = int(conv.size());
26 if(*i==max_son[x]||*i==pa[x])continue;
31 for(int i = 0 ; i < sz ; ++i){
27 build_link(*i,*i);
32 sum += (conv[i].cross(conv[(i+1)%sz]));
28 }
33 }
29 }
34 return double(abs(sum))/double(2);
30 inline int find_lca(int a,int b){
35 }
31 /*求LCA, 可 以 在 過 程 中 對 區 間 進 行 處 理*/
32 int ta=link_top[a],tb=link_top[b];
while(ta!=tb){
9 Data Structure 33
34 if(dep[ta]<dep[tb]){
9.1 BIT 35 std::swap(ta,tb);
36 std::swap(a,b);
NTNU_import_magic 7
37 } 9.6 Treap
38 //這 裡 可 以 對a所 在 的 鏈 做 區 間 處 理
39 //區 間 為(link[ta],link[a]) 1 struct node{
40 ta=link_top[a=pa[ta]]; 2 node *l,*r;
41 } 3 int key,pri,size;
42 /*最 後a,b會 在 同 一 條 鏈 , 若a!=b還 要 在 進 行 一 次 區 間 處 4 node(int k):l(0),r(0),key(k),pri(rand()),size(1){}
理*/ 5 void up();
43 return dep[a]<dep[b]?a:b; 6 };
44 } 7 void node::up(){
8 size=1;
9 if(l)size+=l->size;
9.4 Disjoint Set 10 if(r)size+=r->size;
11 }
1 struct disjointset { // union by rank 12 node *merge(node *a,node *b){
2 int f[MAX], rank[MAX]; 13 if(!a||!b)return a?a:b;
3 void init(int N) { 14 if(a->pri<b->pri){
4 memset(rank,0,sizeof(rank)); 15 a->r=merge(a->r,b);
5 for(int i = 0; i <= N; i++) f[i] = i; 16 a->up();
6 } 17 return a;
7 int find(int val) { 18 }else{
8 return f[val] == val ? val : f[val] = find(f[ 19 b->l=merge(a,b->l);
val]); 20 b->up();
9 } 21 return b;
10 bool same(int a, int b) { 22 }
11 return find(a) == find(b); 23 }
12 } 24 void split(node *o,node *&a,node *&b,int k){
13 void Union(int l, int r) { 25 if(!o)a=b=0;
14 if(!same(l, r)) { 26 else{
15 if(rank[l] < rank[r]) swap(l, r); 27 if( o->key < k ){
16 f[f[r]] = f[l]; 28 a=o;
17 rank[l]++; 29 split(o->r,a->r,b,k);
18 } 30 }else{
19 } 31 b=o;
20 }; 32 split(o->l,a,b->l,k);
33 }
34 o->up();
9.5 Segment Tree 35 }
36 }
37 bool erase(node *&o,int k){
1 class StTree{
2 private: 38 if(!o)return 0;
3 long long l,r,m; 39 if( o->key == k ){
4 StTree *lchild, *rchild; 40 node *t = o;
5 public: 41 o = merge(o->l,o->r);
6 int val; 42 delete t;
7 StTree(long long l,long long r){this->l = l; this 43 return 1;
->r = r; this->m = (l+r)/2; this->val = 0; 44 }
this->lchild=nullptr;this->rchild=nullptr;}; 45 node *&t= k < o->key ? o->l : o->r;
8 void modify(long long i){ 46 if(erase(t,k))return o->up(),1;
47 else return 0;
9 if(l == r && i == l){
10 val++; 48 }
11 return; 49 inline int size(node *o){
12 } 50 return o ? o->size : 0;
13 if(i > m){ 51 }
14 if(rchild == nullptr) rchild = new StTree( 52 int Rank(node *&root,int key){
53 node *a, *b;
m+1,r);
54 split(root,a,b,key);
15 rchild->modify(i);
55 int res = size(a);
16 }
56 root = merge(a,b);
17 else{
57 return res;
18 if(lchild == nullptr) lchild = new StTree(
58 }
l,m);
19 lchild->modify(i);
20 } 10 String
21 val = ((lchild != nullptr)?lchild->val:0) + ((
rchild != nullptr)?rchild->val:0); 10.1 Manacher
22 }
23 int query(long long L,long long R){ 1 #define maxEP(x) (max_element((x).begin(), (x).end()))
24 if(l >= L && r <= R) return val; -(x).begin()
25 if(l < L && r > R) return 0; 2 #define maxE(x) (*max_element((x).begin(), (x).end()))
26 return ((lchild != nullptr)?lchild->query(L,R) 3 vector<int> p(MAX); string new_str;
:0) + ((rchild != nullptr)?rchild->query( 4 void generate_new_string(string s){ // generate the
L,R):0); new string
27 } 5 new_str.insert(0, "@");
28 }; 6 for(int i = 0; i < s.size(); i++) {
7 new_str += "#";
NTNU_import_magic 8
8 new_str += s[i]; 9 h_base[0]=1;
9 } 10 for(int i=1;i<=len;++i){
10 new_str += "#$"; 11 h[i]=(h[i-1]*prime+s[i-1])%prime_mod;
11 } 12 h_base[i]=(h_base[i-1]*prime)%prime_mod;
12 pair<int,int> manacher(string s) { 13 }
13 // find the half length and center position of the 14 }
longest substring palindrome 15 inline T get_hash(int l,int r){/*閉 區 間 寫 法 , 設 編 號 為0
14 for(int i=0;i<MAX;i++) p[i]=0; ~ len-1*/
15 int len = s.size(), Center = 0, R = 0; 16 return (h[r+1]-(h[l]*h_base[r-l+1])%prime_mod+
16 for(int i = 0; i < len; i++) { prime_mod)%prime_mod;
17 int mirror = 2 * Center - i; 17 }
18 if(i + p[mirror] < R) p[i] = min(p[mirror], R
- i);
19 while(s[i + (1 + p[i])] == s[i - (1 + p[i])])
p[i]++;
20 if(i + p[i] > R) {
21 Center = i;
22 R = i + p[i];
23 }
24 }
25 return make_pair(maxE(p),maxEP(p));
26 // .first = the half size of palindrome
27 // .second = the position of the palindrome center
28 }
29 void print_the_longest_substring_palindrome(int pa_len
, int center_pos){
30 // pa_len=manacher.first, center_pos=manacher.
second;
31 for(int i=pos-pa_len;i<pos+pa_len;i++)
32 if(new_s[i]!='#') cout << new_s[i];
33 }

10.2 Failure Function/KMP

1 inline void failure(string& str){


2 // F[] -> the failure function table
3 F[0]=-1;
4 int sz=str.size();
5 for(int i=1,j=-1;i<sz;i++){
6 while(j>=0 && str[j+1]!=str[i]) j=F[j];
7 if(str[j+1]==str[i]) j++;
8 F[i]=j;
9 }
10 }
11 inline vector<int> KMP(string& str, string& comp){
12 failure(comp);
13 vector<int> ans;
14 // the numbers in vector are the " matching head
position of str"
15 int len=str.size(),j=-1;
16 for(int i=0;i<len;i++){
17 while(j>=0 && comp[j+1]!=str[i]) j=F[j];
18 if(comp[j+1]==str[i]) j++;
19 if(j+1==comp.size()){ /* Match!!! */
20 ans.emplace_back(i-j);
21 j=F[j];
22 }
23 }
24 return ans;
25 }

10.3 Rolling Hash/KMP

1 #define MAXN 1000000


2 #define prime_mod 1073676287
3 /*prime_mod 必 須 要 是 質 數*/
4 typedef long long T;
5 char s[MAXN+5];
6 T h[MAXN+5];/*hash陣 列*/
7 T h_base[MAXN+5];/*h_base[n]=(prime^n)%prime_mod*/
8 inline void hash_init(int len,T prime=0xdefaced){

You might also like