├── 笔记.pdf ├── STL笔记.pdf ├── 刷题笔记.pdf ├── 背包九讲.pdf ├── 经典算法笔记.pdf ├── 模板代码 ├── tmp.cpp ├── readWrite.cpp ├── disjointSet.cpp ├── binaryGraphMatching.cpp ├── treeArray.cpp ├── maxFlow.cpp ├── spfa.cpp ├── dijkstra.cpp └── KMP.cpp └── README.md /笔记.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EricLee8/BaoYan-Algorithm-Problems/HEAD/笔记.pdf -------------------------------------------------------------------------------- /STL笔记.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EricLee8/BaoYan-Algorithm-Problems/HEAD/STL笔记.pdf -------------------------------------------------------------------------------- /刷题笔记.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EricLee8/BaoYan-Algorithm-Problems/HEAD/刷题笔记.pdf -------------------------------------------------------------------------------- /背包九讲.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EricLee8/BaoYan-Algorithm-Problems/HEAD/背包九讲.pdf -------------------------------------------------------------------------------- /经典算法笔记.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EricLee8/BaoYan-Algorithm-Problems/HEAD/经典算法笔记.pdf -------------------------------------------------------------------------------- /模板代码/tmp.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 50000; 2 | int trees[MAXN]; 3 | int n; 4 | 5 | int lowbit(int x) {return x&(-x);} 6 | 7 | void tadd(int x, int k) 8 | { 9 | while(x<=n) 10 | { 11 | trees[x] += k; 12 | x += lowbit(x); 13 | } 14 | } 15 | 16 | int tsearch(int x) 17 | { 18 | int ans = 0; 19 | while(x) 20 | { 21 | ans += trees[x]; 22 | x -= lowbit(x); 23 | } 24 | return ans; 25 | } -------------------------------------------------------------------------------- /模板代码/readWrite.cpp: -------------------------------------------------------------------------------- 1 | inline int read() 2 | { 3 | int X = 0; 4 | char ch = 0; while (ch < '0' || ch > '9') ch = getchar(); 5 | while (ch >= '0' && ch <= '9') X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar(); 6 | return X; 7 | } 8 | 9 | inline void write(int x) 10 | { 11 | int y = 10, len = 1; 12 | while (y <= x) { y *= 10; len++; } 13 | while (len--) { y /= 10; putchar(x / y + 48); x %= y; } 14 | } -------------------------------------------------------------------------------- /模板代码/disjointSet.cpp: -------------------------------------------------------------------------------- 1 | class disjointset{ 2 | public: 3 | int *parent; 4 | disjointset(int n) 5 | { 6 | parent = new int[n]; 7 | for(int i=0; i parent[root2]) parent[root2] += parent[root1], parent[root1] = root2; 18 | else parent[root1] += parent[root2], parent[root2] = root1; 19 | } 20 | }; -------------------------------------------------------------------------------- /模板代码/binaryGraphMatching.cpp: -------------------------------------------------------------------------------- 1 | const int N = 105; 2 | bool line[N][N]; 3 | bool used[N]; 4 | int result[N]; 5 | int n, m; 6 | 7 | bool found(int x) 8 | { 9 | for(int i=1; i<=m; i++) 10 | { 11 | if(!used[i] && line[x][i]) 12 | { 13 | used[i] = true; 14 | if(result[i]==0 || found(result[i])) 15 | { 16 | result[i] = x; 17 | return true; 18 | } 19 | } 20 | } 21 | return false; 22 | } 23 | 24 | int main() 25 | { 26 | int cnt = 0; 27 | memset(line, 0, sizeof(line)); 28 | memset(result, 0, sizeof(result)); 29 | // ... construct array line according to the problem 30 | for(int i=1; i<=n; i++) 31 | { 32 | memset(used, 0, sizeof(used)); 33 | if(found(i)) cnt++; 34 | } 35 | cout << cnt << endl; 36 | return 0; 37 | } 38 | 39 | // 2020.07.11默写 40 | const int N = 105; 41 | bool line[N][N]; 42 | int result[N]; 43 | bool used[N]; 44 | int n, m; 45 | 46 | bool found(int x) 47 | { 48 | for(int i=1; i<=m; i++) 49 | { 50 | if(line[x][i] && !used[i]) 51 | { 52 | used[i] = true; 53 | if(result[i]==0 || found(result[i])) 54 | { 55 | result[i] = x; 56 | return true; 57 | } 58 | } 59 | } 60 | return false; 61 | } 62 | 63 | int main() 64 | { 65 | memset(result, 0, sizeof(result)); 66 | memset(line, 0, sizeof(line)); 67 | //constructing binary graph... 68 | int ans = 0; 69 | for(int i=1; i<=n; i++) 70 | { 71 | memset(used, 0, sizeof(used)); 72 | if(found(i)) ans++; 73 | } 74 | cout << ans << endl; 75 | return 0; 76 | } -------------------------------------------------------------------------------- /模板代码/treeArray.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | const int MAXN = 100005; 6 | int trees[MAXN]; 7 | int a[MAXN]; 8 | 9 | int n; //下标要从1开始 10 | 11 | int lowbit(x) {return x&(-x);} 12 | 13 | void tadd(int x, int k) // x的地方加上k 14 | { 15 | while(x<=n) 16 | { 17 | trees[x] += k; 18 | x += lowbit(x); // 找父节点 19 | } 20 | } 21 | 22 | int tsearch(int x) // 搜索x之前的前缀和 23 | { 24 | int ans = 0; 25 | while(x) 26 | { 27 | ans += trees[x]; 28 | x -= lowbit(x); // 找x的前继节点 29 | } 30 | return ans; 31 | } 32 | 33 | //维护区间最值 34 | void tadd(int x, int k) // 仅建树的时候可以用 35 | { 36 | while(x <= n) 37 | { 38 | trees[x] = max(trees[x], k); 39 | x += lowbit(x); 40 | } 41 | } 42 | /* 43 | 说一下为什么只有建树的时候才可以用,而update的时候不能用。因为假如你修改的是位置x的值为k,并且你是维护最大值,那么你层层往上更新和这个 44 | 点有关的trees的值时,假如用的还是max(trees[x], k),那么假如之前tress[x]里存的最大值恰好是这里位置为x的值,而你这次的k又把这个a[x]改 45 | 小了,那么你这次修改其实并不能反映出这个信息,因为你max一下还是之前的值。所以update函数要另外写一个。 46 | */ 47 | 48 | 49 | int tsearch(int x, int y) 50 | { 51 | int ans = -1; 52 | while(y>=x) 53 | { 54 | ans = max(ans, a[y--]); //先这样搞一下,减少一下y,反正也不亏,还能预防y-lowbit(y)爆出去(小于x) 55 | for(; y-lowbit(y)>=x; y-=lowbit(y)) 56 | ans = max(ans, trees[y]); 57 | } 58 | return ans; 59 | } 60 | /* 61 | 关于最值维护的tsearch说明一下,这里最重要的地方就是理解trees[i]的含义:trees[i]里储存的是从a[i-lowbit(i)+1]到a[i] 62 | 的最大值,而我们在求一段区间[x,y]内的最大值时,若发现y-lowbit(y)>=x,我们就可以用max(ans, trees[y])来求得这一段区间的最值 63 | (因为这段区间包含在我们的目标区间内)。而当y-lowbit(y)=x。不断重复直至y不满足y>=x跳出去。 65 | */ 66 | 67 | void update(int x) //之前已经更新了a[x] = k; 68 | { 69 | int lx, i; 70 | while(x <= n) 71 | { 72 | trees[x] = a[x]; 73 | lx = lowbit(x); 74 | for(int i=1; i 2 | 3 | const int MAXN = 10005; 4 | const int MAXM = 1000005*2; 5 | 6 | int head[MAXN], cur[MAXN], dis[MAXN], n, s, t, cnt=1; // start, terminate 7 | bool vis[MAXN]; 8 | 9 | struct edge{ 10 | int to, next, val; 11 | }e[MAXM]; 12 | 13 | void add(int u, int v, int w) 14 | { 15 | e[++cnt].to = v; // edge下标从2开始(为了之后的异或1操作服务 16 | e[cnt].val = w; 17 | e[cnt].next = head[u]; 18 | head[u] = cnt; 19 | } 20 | 21 | bool bfs() 22 | { 23 | for(int i=0; i<=n; i++) vis[i]=0, cur[i]=head[i]; 24 | queue q; 25 | q.push(s); dis[s]=0; vis[s]=1; 26 | int u, v; 27 | while(q.size()) 28 | { 29 | u = q.front(); q.pop(); 30 | for(int i=head[u]; i; i=e[i].next) 31 | { 32 | v = e[i].to; 33 | if(!vis[v] && e[i].val>0) 34 | { 35 | dis[v] = dis[u]+1; 36 | vis[v] = 1; 37 | if(v == t) return true; 38 | q.push(v); 39 | } 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | int dfs(int now, int flow) // now是当前处理节点,而flow是带进当前节点的流量大小 46 | { 47 | if(flow==0 || now==t) return flow; 48 | int used = 0, v; // used表示用掉了多少当前带进来的流量了 49 | for(int i=cur[now]; i; i=e[i].next) // i=cur[now]是进行了当前边优化,即再次访问到该节点时,之前处理过的边不用再处理了 50 | { 51 | cur[now] = i; // 当前边优化 52 | v = e[i].to; 53 | if(dis[v] != dis[now]+1) continue; //这个不要忘啊!!!!!!! 54 | int tmp = dfs(v, min(flow-used, e[i].val));//探索下一个点,送入的流量要么是当前剩余流量全用完(flow-used)要么是下一条边的容量全用完(e[i].val) 55 | if(tmp) 56 | { 57 | e[i] -= tmp; 58 | e[i^1] += tmp; 59 | used += tmp; 60 | if(flow-used == 0) return flow; 61 | } 62 | } 63 | return used; 64 | } 65 | 66 | int dinic() 67 | { 68 | int ans = 0; 69 | while(bfs()) 70 | ans += dfs(s, 0x7fffffff); 71 | return ans; 72 | } 73 | -------------------------------------------------------------------------------- /模板代码/spfa.cpp: -------------------------------------------------------------------------------- 1 | # include 2 | 3 | int m, n, start; 4 | const int MAXN = 205; 5 | bool vis[MAXN]; 6 | bool dis[MAXN]; 7 | 8 | class node{ 9 | public: 10 | int to, len; 11 | node() {} 12 | node(int t, int l): to(t), len(l) {} 13 | }; 14 | 15 | vector* adjList; 16 | 17 | void spfa() 18 | { 19 | memset(vis, 0, sizeof(vis)); 20 | memset(dis, 0x3f, sizeof(dis)); 21 | queue q; 22 | q.push(start); dis[start] = 0; vis[start] = true; 23 | int u, v, tmplen; 24 | while(q.size()) 25 | { 26 | u = q.front(); q.pop(); 27 | vis[u] = false; 28 | for(int i=0; i dis[u] + tmplen) 33 | { 34 | dis[v] = dis[u] + tmplen; 35 | if(!vis[v])q.push(v), vis[v] = true; 36 | } 37 | } 38 | } 39 | } 40 | 41 | 42 | // 2020.06.06默写 43 | const int MAXN = 1005; 44 | int n, start; 45 | bool vis[MAXN]; 46 | int dis[MAXN]; 47 | 48 | class node{ 49 | public: 50 | int to, len; 51 | node() {} 52 | node(int tt, int ll): to(tt), len(ll) {} 53 | }; 54 | 55 | vector* adjList; 56 | 57 | void spfa() 58 | { 59 | memset(vis, 0, sizeof(vis)); 60 | memset(dis, 0x3f, sizeof(dis)); 61 | queue q; 62 | q.push(start); dis[start]=0; vis[start]=true; 63 | int u, v, tmplen; 64 | while(q.size()) 65 | { 66 | u = q.front(); q.pop(); 67 | vis[u] = false; 68 | for(int i=0; i dis[u]+tmplen) 73 | { 74 | dis[v] = dis[u]+tmplen; 75 | if(!vis[v]) q.push(v), vis[v] = true; 76 | } 77 | } 78 | } 79 | } 80 | 81 | 82 | //2020.07.03默写 83 | const int MAXN = 10005; 84 | bool vis[MAXN]; 85 | int dis[MAXN]; 86 | int start; 87 | 88 | class node{ 89 | public: 90 | int to, len; 91 | node() {} 92 | node(int tt, int ll): to(tt), len(ll) {} 93 | }; 94 | 95 | vector *adjList; 96 | 97 | void spfa() 98 | { 99 | memset(vis, 0, sizeof(vis)); 100 | memset(dis, 0x7f, sizeof(dis)); 101 | queue q; 102 | q.push(start); dis[start]=0; vis[start]=true; 103 | int u, v, tmplen; 104 | while(q.size()) 105 | { 106 | u = q.front(); q.pop(); 107 | vis[u] = false; 108 | for(int i=0; i tmplen) 113 | { 114 | dis[v] = tmplen; 115 | if(!vis[v]) q.push(v), vis[v]=true; 116 | } 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /模板代码/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | # include 2 | 3 | int m, n, start; 4 | const int MAXN = 205; 5 | bool vis[MAXN]; 6 | int dis[MAXN]; 7 | 8 | class node{ 9 | public: 10 | int to, len; 11 | node() {} 12 | node(int t, int l): to(t), len(l) {} 13 | bool operator < (const node& n2) const {return len > n2.len;} //小根堆 14 | }; 15 | 16 | vector* adjList; 17 | 18 | void dijkstra() 19 | { 20 | memset(vis, 0, sizeof(vis)); 21 | memset(dis, 0x3f, sizeof(dis)); 22 | priority_queue q; 23 | q.push(node(start, 0)); dis[start] = 0; 24 | node tmp; 25 | int u, v, tmplen; 26 | while(q.size()) 27 | { 28 | tmp = q.top(); q.pop(); 29 | u = tmp.to; 30 | if(vis[u]) continue; 31 | vis[u] = true; 32 | for(int i=0; i tmplen) 37 | { 38 | dis[v] = tmplen; 39 | q.push(node(v, dis[v])); 40 | } 41 | } 42 | } 43 | } 44 | 45 | 46 | // 2020.06.05默写 47 | const int MAXN = 10005; 48 | int strat; 49 | 50 | bool vis[MAXN]; 51 | int dis[MAXN]; 52 | 53 | class node{ 54 | public: 55 | int to, len; 56 | node() {} 57 | node(int tt, int ll): to(tt), len(ll) {} 58 | bool operator <(const node& n2) const {return len>n2.len;} 59 | }; 60 | 61 | vector *adjList; 62 | 63 | void dijkstra() 64 | { 65 | memset(vis, 0, sizeof(vis)); 66 | memset(dis, 0x3f, sizeof(dis)); 67 | priority_queue q; 68 | q.push(node(start, 0)); dis[start] = 0; 69 | node tmp; int u, v, tmplen; 70 | while(q.size()) 71 | { 72 | tmp = q.top(); q.pop(); 73 | u = tmp.to; 74 | if(vis[u]) continue; 75 | vis[u] = true; 76 | for(int i=0; itmplen) 81 | { 82 | dis[v] = tmplen; 83 | q.push(node(v, dis[v])); 84 | } 85 | } 86 | } 87 | } 88 | 89 | //2020.07.03默写 90 | const int MAXN = 10000; 91 | bool vis[MAXN]; 92 | int dis[MAXN]; 93 | int start; 94 | 95 | class node{ 96 | public: 97 | int to, len; 98 | node() {} 99 | node(int tt, int ll): to(tt), len(ll) {} 100 | bool operator < (const node& n2) const {return len>n2.len;} //最小化堆 101 | }; 102 | 103 | vector *adjList; 104 | 105 | void dijkstra() 106 | { 107 | memset(dis, 0x3f, sizeof(dis)); 108 | memset(vis, 0, sizeof(vis)); 109 | priority_queue q; 110 | q.push(node(start, 0)); dis[start]=0; 111 | node tmp; int u, v, tmplen; 112 | while(q.size()) 113 | { 114 | tmp = q.top(); q.pop(); 115 | u = tmp.to; 116 | if(vis[u]) continue; 117 | vis[u] = true; 118 | for(int i=0; idis[u]+tmplen) 123 | { 124 | dis[v] = dis[u]+tmplen; 125 | q.push(node(v, dis[v])); 126 | } 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /模板代码/KMP.cpp: -------------------------------------------------------------------------------- 1 | int KMP(string text, string pattern) 2 | { 3 | int i, j, m = pattern.size(), n = text.size(); 4 | int* nxt = new int [m]; 5 | nxt[0] = -1; // nxt[i]表示i这个位置前后缀相等的最大前缀的最后一个字符的下标哈 6 | for(int i=1; i=0 && pattern[nxt[j]+1]!=pattern[i]) j = nxt[j]; //如果不相等就一直往nxt[j]找下去直到相等或者j<0 10 | if(j<0) nxt[i] = -1; 11 | else nxt[i] = nxt[j]+1; //刚刚相等的那个地方 12 | } 13 | 14 | i = j = 0; //开始从头匹配 15 | while(i=0 && pattern[nxt[j]+1]!=pattern[i]) j = nxt[j]; 36 | if(j<0) nxt[i] = -1; 37 | else nxt[i] = nxt[j] + 1; 38 | } 39 | i = j = 0; 40 | while(i=0 && pattern[nxt[j]+1]!=pattern[i]) j = nxt[j]; 61 | if(j<0) nxt[i] = -1; 62 | else nxt[i] = nxt[j]+1; 63 | } 64 | i = j = 0; 65 | while(i=0 && pattern[nxt[j]+1]!=pattern[i]) j = nxt[j]; 87 | if(j<0) nxt[i] = -1; 88 | else nxt[i] = nxt[j] + 1; 89 | } 90 | // ========================= 多重匹配 =========================== 91 | i = j = 0; 92 | while(i=0 && pattern[nxt[j]+1]!=pattern[i]) j = nxt[j]; 116 | if(j<0) nxt[i] = -1; 117 | else nxt[i] = nxt[j]+1; 118 | } 119 | //默写一下多重匹配的 120 | i = j =0; 121 | int num = 0; 122 | while(i