算法模板の数据结构
一、平衡树
1、treap树
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int key[MAXN], weight[MAXN], child[MAXN][2], size[MAXN]; 2 int stk[MAXN], top, poi_cnt;//not use point 3 4 inline int newNode(int k) { 5 int x = (top ? stk[top--] : ++poi_cnt); 6 key[x] = k; 7 size[x] = 1; 8 weight[x] = rand(); 9 child[x][0] = child[x][1] = 0; 10 return x; 11 } 12 13 inline void update(int &x) { 14 size[x] = size[child[x][0]] + size[child[x][1]] + 1;//size[0]=0 15 } 16 17 inline void rotate(int &x, int t) { 18 int y = child[x][t]; 19 child[x][t] = child[y][t ^ 1]; 20 child[y][t ^ 1] = x; 21 update(x); update(y); 22 x = y; 23 } 24 25 void insert(int &x, int k) { 26 if (x == 0) x = newNode(k); 27 else { 28 int t = (key[x] < k); 29 insert(child[x][t], k); 30 if (weight[child[x][t]] < weight[x]) rotate(x, t); 31 } 32 update(x); 33 } 34 35 void remove(int &x, int k) { 36 if(key[x] == k) { 37 if(child[x][0] && child[x][1]) { 38 int t = weight[child[x][0]] < weight[child[x][1]]; 39 rotate(x, t); remove(child[x][t ^ 1], k); 40 } 41 else { 42 stk[++top] = x; 43 x = child[x][0] + child[x][1]; 44 } 45 } 46 else remove(child[x][key[x] < k], k); 47 if(x > 0) update(x); 48 } 49 50 int kth(int &x, int k) { 51 if(x == 0 || k <= 0 || k > size[x]) return 0; 52 int s = 0; 53 if(child[x][1]) s = size[child[x][1]]; 54 if(k == s + 1) return key[x]; 55 if(k <= s) return kth(child[x][1], k); 56 return kth(child[x][0], k - s - 1); 57 }
2、伸展树
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 struct SplayTree {//左右各有一个空结点 2 struct Node { 3 int size, lhash, rhash; 4 char c; 5 Node *fa, *ch[2]; 6 }; 7 Node statePool[MAXN], *nil, *root; 8 int stk[MAXN], top; 9 int ncnt; 10 11 void init() { 12 nil = statePool; 13 ncnt = 1; 14 top = 0; 15 } 16 17 Node* new_node(char v, Node* f) { 18 Node* t; 19 if(top) t = &statePool[stk[--top]]; 20 else t = &statePool[ncnt++]; 21 t->size = 1; 22 t->lhash = t->rhash = t->c = v; 23 t->ch[0] = t->ch[1] = nil; 24 t->fa = f; 25 return t; 26 } 27 28 void del_node(Node* &x) { 29 stk[top++] = x - statePool; 30 x = nil; 31 } 32 33 void rotate(Node* x) { 34 Node* y = x->fa; 35 int t = (y->ch[1] == x); 36 y->fa->ch[y->fa->ch[1] == y] = x; x->fa = y->fa; 37 y->ch[t] = x->ch[t ^ 1]; x->ch[t ^ 1]->fa = y; 38 x->ch[t ^ 1] = y; y->fa = x; 39 update(y); 40 } 41 42 void splay(Node* x, Node* f) { 43 while(x->fa != f) { 44 if(x->fa->fa == f) rotate(x); 45 else { 46 Node *y = x->fa, *z = y->fa; 47 if((z->ch[1] == y) == (y->ch[1] == x)) rotate(y); 48 else rotate(x); 49 rotate(x); 50 } 51 } 52 update(x); 53 if(x->fa == nil) root = x; 54 } 55 56 Node* kth(int k) { 57 Node* x = root; 58 while(true) { 59 int t = x->ch[0]->size + 1; 60 if(t == k) break; 61 if(t > k) x = x->ch[0]; 62 else x = x->ch[1], k -= t; 63 } 64 return x; 65 } 66 67 void insert(int pos, char c) { 68 splay(kth(pos), nil); 69 splay(kth(pos + 1), root); 70 root->ch[1]->ch[0] = new_node(c, root->ch[1]); 71 update(root->ch[1]); update(root); 72 } 73 74 void modify(int pos, char c) { 75 splay(kth(pos), nil); 76 root->c = c; 77 update(root); 78 } 79 80 void remove(int pos) { 81 splay(kth(pos - 1), nil); 82 splay(kth(pos + 1), root); 83 del_node(root->ch[1]->ch[0]); 84 update(root->ch[1]); update(root); 85 } 86 } splay;
二、其他
1、左偏树(HDU 1512)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int MAXN = 100010; 7 8 int n, m; 9 int fa[MAXN]; 10 11 int key[MAXN], child[MAXN][2], dist[MAXN]; 12 int stk[MAXN], top, node_cnt; 13 int root[MAXN]; 14 15 void init() { 16 dist[0] = -1; 17 top = node_cnt = 0; 18 } 19 20 int newNode(int k) { 21 int x = top ? stk[top--] : ++node_cnt; 22 dist[x] = 1; key[x] = k; 23 child[x][0] = child[x][1] = 0; 24 return x; 25 } 26 27 void maintain(int &x) { 28 if(dist[child[x][0]] < dist[child[x][1]]) 29 swap(child[x][0], child[x][1]); 30 dist[x] = dist[child[x][0]] + 1; 31 } 32 33 int merge(int &x, int &y) { 34 if(x == 0) return y; 35 if(y == 0) return x; 36 if(key[y] > key[x]) swap(x, y); 37 child[x][1] = merge(child[x][1], y); 38 maintain(x); 39 return x; 40 } 41 42 int del(int &x) { 43 if(x != 0) { 44 stk[++top] = x; 45 return merge(child[x][0], child[x][1]); 46 } 47 return 0; 48 } 49 50 int getfather(int x) { 51 return fa[x] == x ? x : fa[x] = getfather(fa[x]); 52 } 53 54 int merge2(int x, int y) { 55 return fa[x] = y; 56 } 57 58 void solve(int u, int v) { 59 int fu = getfather(u); 60 int fv = getfather(v); 61 if(fu == fv) { 62 printf("-1\n"); 63 return ; 64 } 65 int p1 = newNode(key[root[fu]] / 2); 66 int p2 = newNode(key[root[fv]] / 2); 67 int p3 = del(root[fu]); 68 int p4 = del(root[fv]); 69 p3 = merge(p1, p3); 70 p4 = merge(p2, p4); 71 int x = merge2(fu, fv); 72 root[x] = merge(p3, p4); 73 printf("%d\n", key[root[x]]); 74 } 75 76 int main() { 77 int k, u, v; 78 while(scanf("%d", &n) != EOF) { 79 init(); 80 for(int i = 1; i <= n; ++i) { 81 scanf("%d", &k); 82 root[i] = newNode(k); 83 fa[i] = i; 84 } 85 scanf("%d", &m); 86 while(m--) { 87 scanf("%d%d", &u, &v); 88 solve(u, v); 89 } 90 } 91 }
2、RMQ+LCA(在线)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int RMQ[2*MAXN], mm[2*MAXN], best[20][2*MAXN]; 2 3 void initMM() { 4 mm[0] = -1; 5 for(int i = 1; i <= MAXN * 2 - 1; ++i) 6 mm[i] = ((i&(i-1)) == 0) ? mm[i-1] + 1 : mm[i-1]; 7 } 8 9 void initRMQ(int n) { 10 int i, j, a, b; 11 for(i = 1; i <= n; ++i) best[0][i] = i; 12 for(i = 1; i <= mm[n]; ++i) { 13 for(j = 1; j <= n + 1 - (1 << i); ++j) { 14 a = best[i - 1][j]; 15 b = best[i - 1][j + (1 << (i - 1))]; 16 if(RMQ[a] < RMQ[b]) best[i][j] = a; 17 else best[i][j] = b; 18 } 19 } 20 } 21 22 int askRMQ(int a,int b) { 23 int t; 24 t = mm[b - a + 1]; b -= (1 << t)-1; 25 a = best[t][a]; b = best[t][b]; 26 return RMQ[a] < RMQ[b] ? a : b; 27 } 28 29 int dfs_clock, num[2*MAXN], pos[MAXN];//LCA 30 31 void dfs_LCA(int f, int u, int dep) { 32 pos[u] = ++dfs_clock; 33 RMQ[dfs_clock] = dep; num[dfs_clock] = u; 34 for(int p = head[u]; p; p = next[p]) { 35 if(to[p] == f) continue; 36 dfs_LCA(u, to[p], dep + 1); 37 ++dfs_clock; 38 RMQ[dfs_clock] = dep; num[dfs_clock] = u; 39 } 40 } 41 42 int LCA(int u, int v) { 43 if(pos[u] > pos[v]) swap(u, v); 44 return num[askRMQ(pos[u], pos[v])]; 45 } 46 47 void initLCA(int n) { 48 dfs_clock = 0; 49 dfs_LCA(0, root, 0); 50 initRMQ(dfs_clock); 51 }
3、主席树(POJ 2104)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int MAXN = 100010; 6 7 struct Node { 8 int L, R, sum; 9 }; 10 Node T[MAXN * 20]; 11 int T_cnt; 12 13 void insert(int &num, int &x, int L, int R) { 14 T[T_cnt++] = T[x]; x = T_cnt - 1; 15 ++T[x].sum; 16 if(L == R) return ; 17 int mid = (L + R) >> 1; 18 if(num <= mid) insert(num, T[x].L, L, mid); 19 else insert(num, T[x].R, mid + 1, R); 20 } 21 22 int query(int i, int j, int k, int L, int R) { 23 if(L == R) return L; 24 int t = T[T[j].L].sum - T[T[i].L].sum; 25 int mid = (R + L) >> 1; 26 if(k <= t) return query(T[i].L, T[j].L, k, L, mid); 27 else return query(T[i].R, T[j].R, k - t, mid + 1, R); 28 } 29 30 struct A { 31 int x, idx; 32 bool operator < (const A &rhs) const { 33 return x < rhs.x; 34 } 35 }; 36 37 A a[MAXN]; 38 int rank[MAXN], root[MAXN]; 39 int n, m; 40 41 int main() { 42 T[0].L = T[0].R = T[0].sum = 0; 43 root[0] = 0; 44 while(scanf("%d%d", &n, &m) != EOF) { 45 for(int i = 1; i <= n; ++i) { 46 scanf("%d", &a[i].x); 47 a[i].idx = i; 48 } 49 sort(a + 1, a + n + 1); 50 for(int i = 1; i <= n; ++i) rank[a[i].idx] = i; 51 T_cnt = 1; 52 for(int i = 1; i <= n; ++i) { 53 root[i] = root[i - 1]; 54 insert(rank[i], root[i], 1, n); 55 } 56 while(m--) { 57 int i, j, k; 58 scanf("%d%d%d", &i, &j, &k); 59 printf("%d\n", a[query(root[i - 1], root[j], k, 1, n)].x); 60 } 61 } 62 }
4、树状数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int lowbit(int x) { 2 return x & (-x); 3 } 4 5 int get_sum(int k) { 6 int ans = 0; 7 while(k > 0) { 8 ans += tree[k]; 9 k -= lowbit(k); 10 } 11 return ans; 12 } 13 14 void modify(int k, int val) { 15 while(k <= n) { 16 tree[k] += val; 17 k += lowbit(k); 18 } 19 }
5、DLX舞蹈链
①POJ 3076
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 const int MAXC = 1024 + 10; 9 const int MAXR = 4096 + 10; 10 const int MAXP = MAXR * 4 + MAXC; 11 12 struct DLX { 13 int n, sz;//列数,结点总数 14 int sum[MAXC];//每列拥有的结点数 15 int row[MAXP], col[MAXP];//结点所在的行和列 16 int left[MAXP], right[MAXP], up[MAXP], down[MAXP];//十字链表 17 int ansd, ans[MAXR]; 18 19 void init(int nn) { 20 n = nn; 21 for(int i = 0; i <= n; ++i) { 22 up[i] = down[i] = i; 23 left[i] = i - 1; right[i] = i + 1; 24 } 25 right[n] = 0; left[0] = n; 26 sz = n + 1; 27 memset(sum, 0, sizeof(sum)); 28 } 29 30 void add_row(int r, vector<int> columns) { 31 int first = sz; 32 for(int i = 0, len = columns.size(); i < len; ++i) { 33 int c = columns[i]; 34 left[sz] = sz - 1; right[sz] = sz + 1; down[sz] = c; up[sz] = up[c]; 35 down[up[c]] = sz; up[c] = sz; 36 row[sz] = r; col[sz] = c; 37 ++sum[c]; ++sz; 38 } 39 right[sz - 1] = first; left[first] = sz - 1; 40 } 41 42 void remove(int c) { 43 left[right[c]] = left[c]; 44 right[left[c]] = right[c]; 45 for(int i = down[c]; i != c; i = down[i]) 46 for(int j = right[i]; j != i; j = right[j]) { 47 up[down[j]] = up[j]; down[up[j]] = down[j]; --sum[col[j]]; 48 } 49 } 50 51 void restore(int c) { 52 for(int i = up[c]; i != c; i = up[i]) 53 for(int j = left[i]; j != i; j = left[j]) { 54 up[down[j]] = j; down[up[j]] = j; ++sum[col[j]]; 55 } 56 left[right[c]] = c; 57 right[left[c]] = c; 58 } 59 60 bool dfs(int d) { 61 if(right[0] == 0) { 62 ansd = d; 63 return true; 64 } 65 int c = right[0]; 66 for(int i = right[0]; i != 0; i = right[i]) if(sum[i] < sum[c]) c = i; 67 remove(c); 68 for(int i = down[c]; i != c; i = down[i]) { 69 ans[d] = row[i]; 70 for(int j = right[i]; j != i; j = right[j]) remove(col[j]); 71 if(dfs(d + 1)) return true; 72 for(int j = left[i]; j != i; j = left[j]) restore(col[j]); 73 } 74 restore(c); 75 return false; 76 } 77 78 bool solve(vector<int> &v) { 79 v.clear(); 80 if(!dfs(0)) return false; 81 for(int i = 0; i < ansd; ++i) v.push_back(ans[i]); 82 return true; 83 } 84 }; 85 86 DLX solver; 87 88 const int SLOT = 0; 89 const int ROW = 1; 90 const int COL = 2; 91 const int SUB = 3; 92 93 inline int encode(int a, int b, int c) { 94 return a * 256 + b * 16 + c + 1; 95 } 96 97 void decode(int code, int &a, int &b, int &c) { 98 --code; 99 c = code % 16; code /= 16; 100 b = code % 16; code /= 16; 101 a = code; 102 } 103 104 char puzzle[16][20]; 105 106 bool read() { 107 for(int i = 0; i < 16; ++i) 108 if(scanf("%s", puzzle[i]) == EOF) return false; 109 return true; 110 } 111 112 int main() { 113 int kase = 0; 114 while(read()) { 115 if(++kase != 1) printf("\n"); 116 solver.init(1024); 117 for(int r = 0; r < 16; ++r) 118 for(int c = 0; c < 16; ++c) 119 for(int v = 0; v < 16; ++v) 120 if(puzzle[r][c] == '-' || puzzle[r][c] == 'A' + v) { 121 vector<int> columns; 122 columns.push_back(encode(SLOT, r, c)); 123 columns.push_back(encode(ROW, r, v)); 124 columns.push_back(encode(COL, c, v)); 125 columns.push_back(encode(SUB, (r/4)*4+c/4, v)); 126 solver.add_row(encode(r, c, v), columns); 127 } 128 vector<int> ans; 129 solver.solve(ans); 130 for(int i = 0, len = ans.size(); i < len; ++i) { 131 int r, c, v; 132 decode(ans[i], r, c, v); 133 puzzle[r][c] = 'A' + v; 134 } 135 for(int i = 0; i < 16; ++i) printf("%s\n", puzzle[i]); 136 } 137 }
②HDU 4735
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 struct DLX {//HDU 4735 2 int n, sz;//列数,结点总数 3 int sum[MAXC];//每列拥有的结点数 4 int row[MAXP], col[MAXP];//结点所在的行和列 5 int left[MAXP], right[MAXP], up[MAXP], down[MAXP];//十字链表 6 int ans, anst[MAXR]; 7 8 void init(int nn) { 9 n = nn; 10 for(int i = 0; i <= n; ++i) { 11 up[i] = down[i] = i; 12 left[i] = i - 1; right[i] = i + 1; 13 col[i] = i; 14 } 15 right[n] = 0; left[0] = n; 16 sz = n + 1; 17 memset(sum, 0, sizeof(sum)); 18 } 19 20 void add_row(int r, vector<int> &columns) { 21 int first = sz; 22 for(int i = 0, len = columns.size(); i < len; ++i) { 23 int c = columns[i]; 24 left[sz] = sz - 1; right[sz] = sz + 1; down[sz] = c; up[sz] = up[c]; 25 down[up[c]] = sz; up[c] = sz; 26 row[sz] = r; col[sz] = c; 27 ++sum[c]; ++sz; 28 } 29 right[sz - 1] = first; left[first] = sz - 1; 30 } 31 32 void remove(int c) { 33 for(int i = down[c]; i != c; i = down[i]) { 34 left[right[i]] = left[i]; 35 right[left[i]] = right[i]; 36 } 37 } 38 39 void restore(int c) { 40 for(int i = down[c]; i != c; i = down[i]) { 41 left[right[i]] = i; 42 right[left[i]] = i; 43 } 44 } 45 46 bool vis[MAXC]; 47 48 int A() { 49 memset(vis, 0, sizeof(vis)); 50 int ret = 0; 51 for(int i = right[0]; i != 0; i = right[i]) if(!vis[i]) { 52 ++ret; 53 for(int j = down[i]; j != i; j = down[j]) { 54 for(int k = right[j]; k != j; k = right[k]) vis[col[k]] = true; 55 } 56 } 57 return ret; 58 } 59 60 void dfs(int dep) { 61 if(dep + A() > boys) return ; 62 int tmp = 0; 63 for(int i = 0; i < dep; ++i) tmp += boy[anst[i]]; 64 if(dep - tmp >= ans) return ; 65 if(right[0] == 0) { 66 ans = dep - tmp; 67 return ; 68 } 69 int c = right[0]; 70 for(int i = right[0]; i != 0; i = right[i]) if(sum[i] < sum[c]) c = i; 71 for(int i = down[c]; i != c; i = down[i]) { 72 anst[dep] = row[i]; 73 remove(i); 74 for(int j = right[i]; j != i; j = right[j]) remove(j); 75 dfs(dep + 1); 76 for(int j = left[i]; j != i; j = left[j]) restore(j); 77 restore(i); 78 } 79 } 80 81 bool solve() { 82 ans = n + 1; 83 dfs(0); 84 return ans != n + 1; 85 } 86 } S;
6、动态树LCT
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 struct LCT { 2 struct Node { 3 Node *ch[2], *fa; 4 int val; 5 bool rt, rev; 6 } statePool[MAXV], *nil; 7 int ncnt; 8 9 void init() { 10 nil = statePool; 11 ncnt = 1; 12 } 13 14 void rotate(Node *x) { 15 Node *y = x->fa; 16 int t = (y->ch[1] == x); 17 18 if(y->rt) y->rt = false, x->rt = true; 19 else y->fa->ch[y->fa->ch[1] == y] = x; 20 x->fa = y->fa; 21 22 (y->ch[t] = x->ch[t ^ 1])->fa = y; 23 (x->ch[t ^ 1] = y)->fa = x; 24 update(y); 25 } 26 27 void update_rev(Node *x) { 28 if(x == nil) return ; 29 x->rev = !x->rev; 30 swap(x->ch[0], x->ch[1]); 31 } 32 33 void pushdown(Node *x) { 34 if(x->rev) { 35 FOR(k, 2) update_rev(x->ch[k]); 36 x->rev = false; 37 } 38 } 39 40 void push(Node *x) { 41 if(!x->rt) push(x->fa); 42 pushdown(x); 43 } 44 45 void splay(Node *x) { 46 push(x); 47 while(!x->rt) { 48 Node *f = x->fa, *ff = f->fa; 49 if(!f->rt) rotate(((ff->ch[1] == f) && (f->ch[1] == x)) ? f : x); 50 rotate(x); 51 } 52 update(x); 53 } 54 55 Node* access(Node *x) { 56 Node *y = nil; 57 while(x != nil) { 58 splay(x); 59 x->ch[1]->rt = true; 60 (x->ch[1] = y)->rt = false; 61 update(x); 62 y = x; x = x->fa; 63 } 64 return y; 65 } 66 67 void be_root(Node *x) { 68 access(x); 69 splay(x); 70 update_rev(x); 71 } 72 73 void link(Node *x, Node *y) { 74 be_root(x); 75 x->fa = y; 76 } 77 78 void cut(Node *x, Node *y) { 79 be_root(x); 80 access(x); 81 splay(y); 82 y->fa = nil; 83 } 84 85 void modify_set(Node *x, Node *y, int w) { 86 be_root(x); 87 update_set(access(y), w); 88 } 89 90 void query(Node *x, Node *y) { 91 be_root(x); 92 Node *r = access(y); 93 if(r->max[1] == NINF) puts("ALL SAME"); 94 else printf("%d %d\n", r->max[1], r->cnt[1]); 95 } 96 };
7、树链剖分
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int fa[MAXV], size[MAXV], son[MAXV], top[MAXV], tid[MAXV], dep[MAXV]; 2 int dfs_clock; 3 4 void dfs_size(int u, int f, int depth) { 5 fa[u] = f; dep[u] = depth; 6 size[u] = 1; son[u] = 0; 7 int maxsize = 0; 8 for(int p = head[u]; ~p; p = next[p]) { 9 int &v = to[p]; 10 if(v == f) continue; 11 dfs_size(v, u, depth + 1); 12 size[u] += size[v]; 13 if(size[v] > maxsize) { 14 son[u] = v; 15 maxsize = size[v]; 16 } 17 } 18 } 19 20 void dfs_heavy_edge(int u, int ancestor) { 21 tid[u] = ++dfs_clock; top[u] = ancestor; 22 if(son[u]) dfs_heavy_edge(son[u], ancestor); 23 for(int p = head[u]; ~p; p = next[p]) { 24 int &v = to[p]; 25 if(v == fa[u] || v == son[u]) continue; 26 dfs_heavy_edge(v, v); 27 } 28 } 29 30 void modifyFlip(int a, int b) { 31 while(top[a] != top[b]) { 32 if(dep[top[a]] < dep[top[b]]) swap(a, b); 33 modifyFlip(1, 1, n, tid[top[a]], tid[a]); 34 a = fa[top[a]]; 35 } 36 if(a != b) { 37 if(dep[a] < dep[b]) swap(a, b); 38 modifyFlip(1, 1, n, tid[son[b]], tid[a]); 39 } 40 }