Loading docs/ds/lct.md +10 −10 Original line number Diff line number Diff line Loading @@ -127,21 +127,21 @@ #### Splay 系函数(不会多做解释) 1. `Get(x)` 获取 x 是父亲的哪个⼉子。 2. `Splay(x)` 通过和 Rotate 操作联动实现把 x 旋转到<font color = "red">当前 Splay 的根</font>。 3. `Rotate(x)` 将 x 向上旋转一层的操作。 1. `Get(x)` 获取 $x$ 是父亲的哪个⼉子。 2. `Splay(x)` 通过和 Rotate 操作联动实现把 $x$ 旋转到<font color = "red">当前 Splay 的根</font>。 3. `Rotate(x)` 将 $x$ 向上旋转一层的操作。 #### 新操作 1. `IsRoot(x)` 判断当前节点是否是所在 Splay 的根。 2. `Access(x)` 把从根到当前节点的所有点放在⼀条实链里,使根到它成为一条实路径,并且在同一棵 Splay 里。 3. `Update(x)` 在 Access 操作之后,递归地从上到下 Pushdown 更新信息。 4. `MakeRoot(x)` 使 x 点成为整棵辅助树的根。 5. `Link(x, y)` 在 x, y 两点间连⼀一条边。 6. `Cut(x, y)` 把 x, y 两点间边删掉。 7. `Find(x)` 找到 x 所在的 Splay 的根节点编号。 8. `Fix(x, v)` 修改 x 的点权为 v。 9. `Split(x, y)` 提取出 x, y 间的路径,方便做区间操作。 3. `Update(x)` 在 `Access` 操作之后,递归地从上到下 `Pushdown` 更新信息。 4. `MakeRoot(x)` 使 $x$ 点成为整棵辅助树的根。 5. `Link(x, y)` 在 $x, y$ 两点间连⼀一条边。 6. `Cut(x, y)` 把 $x, y$ 两点间边删掉。 7. `Find(x)` 找到 $x$ 所在的 Splay 的根节点编号。 8. `Fix(x, v)` 修改 $x$ 的点权为 $v$ 。 9. `Split(x, y)` 提取出 $x, y$ 间的路径,方便做区间操作。 ### 宏定义 Loading docs/graph/kth-path.md +16 −14 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ using namespace std; const int maxn = 5010; const int maxm = 400010; const int inf = 2e9; int n, m, s, t, k, u, v, ww, H[maxn], cnt[maxn], ans; int n, m, s, t, k, u, v, ww, H[maxn], cnt[maxn]; int cur, h[maxn], nxt[maxm], p[maxm], w[maxm]; int cur1, h1[maxn], nxt1[maxm], p1[maxm], w1[maxm]; bool tf[maxn]; Loading Loading @@ -78,14 +78,13 @@ int main() { q.pop(); cnt[x.x]++; if (x.x == t && cnt[x.x] == k) { printf("%d\n", ans); printf("%d\n", x.v); return 0; ans++; } if (cnt[x.x] > k) continue; for (int j = h[x.x]; j; j = nxt[j]) q.push({p[j], x.v + w[j]}); } printf("%d\n", ans); printf("-1\n"); return 0; } ``` Loading Loading @@ -159,7 +158,7 @@ int main() { #include <queue> using namespace std; const int maxn = 200010; int n, m, s, t, k, x, y, ww, cnt, ans, fa[maxn]; int n, m, s, t, k, x, y, ww, cnt, fa[maxn]; struct Edge { int cur, h[maxn], nxt[maxn], p[maxn], w[maxn]; void add_edge(int x, int y, int z) { Loading Loading @@ -212,7 +211,7 @@ struct LeftistTree { } st; void dfs2(int x) { vis[x] = true; if (fa[x] && fa[x] != n) st.rt[x] = st.merge(st.rt[x], st.rt[fa[x]]); if (fa[x]) st.rt[x] = st.merge(st.rt[x], st.rt[fa[x]]); for (int j = e2.h[x]; j; j = e2.nxt[j]) if (fa[e2.p[j]] == x && !vis[e2.p[j]]) dfs2(e2.p[j]); } Loading @@ -220,7 +219,7 @@ int main() { scanf("%d%d%d%d%d", &n, &m, &s, &t, &k); for (int i = 1; i <= m; i++) scanf("%d%d%d", &x, &y, &ww), e1.add_edge(x, y, ww), e2.add_edge(y, x, ww); Q.push({n, 0}); Q.push({t, 0}); while (!Q.empty()) { a = Q.top(); Q.pop(); Loading @@ -230,10 +229,13 @@ int main() { for (int j = e2.h[a.x]; j; j = e2.nxt[j]) Q.push({e2.p[j], a.v + e2.w[j]}); } if (k == 1) { printf("%d\n", dist[1]); if (tf[s]) printf("%d\n", dist[s]); else printf("-1\n"); return 0; } dfs(n); dfs(t); for (int i = 1; i <= n; i++) if (tf[i]) for (int j = e1.h[i]; j; j = e1.nxt[j]) Loading @@ -243,8 +245,8 @@ int main() { st.rt[i], st.newnode({e1.p[j], dist[e1.p[j]] + e1.w[j] - dist[i]})); for (int i = 1; i <= n; i++) vis[i] = false; dfs2(n); if (st.rt[1]) Q.push({st.rt[1], dist[1] + st.v[st.rt[1]].v}); dfs2(t); if (st.rt[s]) Q.push({st.rt[s], dist[s] + st.v[st.rt[s]].v}); while (!Q.empty()) { a = Q.top(); Q.pop(); Loading @@ -257,10 +259,10 @@ int main() { Q.push({st.lc[a.x], a.v - st.v[a.x].v + st.v[st.lc[a.x]].v}); if (st.rc[a.x]) Q.push({st.rc[a.x], a.v - st.v[a.x].v + st.v[st.rc[a.x]].v}); int t = st.rt[st.v[a.x].x]; if (t) Q.push({t, a.v + st.v[t].v}); x = st.rt[st.v[a.x].x]; if (x) Q.push({x, a.v + st.v[x].v}); } printf("%d\n", ans); printf("-1\n"); return 0; } ``` Loading Loading
docs/ds/lct.md +10 −10 Original line number Diff line number Diff line Loading @@ -127,21 +127,21 @@ #### Splay 系函数(不会多做解释) 1. `Get(x)` 获取 x 是父亲的哪个⼉子。 2. `Splay(x)` 通过和 Rotate 操作联动实现把 x 旋转到<font color = "red">当前 Splay 的根</font>。 3. `Rotate(x)` 将 x 向上旋转一层的操作。 1. `Get(x)` 获取 $x$ 是父亲的哪个⼉子。 2. `Splay(x)` 通过和 Rotate 操作联动实现把 $x$ 旋转到<font color = "red">当前 Splay 的根</font>。 3. `Rotate(x)` 将 $x$ 向上旋转一层的操作。 #### 新操作 1. `IsRoot(x)` 判断当前节点是否是所在 Splay 的根。 2. `Access(x)` 把从根到当前节点的所有点放在⼀条实链里,使根到它成为一条实路径,并且在同一棵 Splay 里。 3. `Update(x)` 在 Access 操作之后,递归地从上到下 Pushdown 更新信息。 4. `MakeRoot(x)` 使 x 点成为整棵辅助树的根。 5. `Link(x, y)` 在 x, y 两点间连⼀一条边。 6. `Cut(x, y)` 把 x, y 两点间边删掉。 7. `Find(x)` 找到 x 所在的 Splay 的根节点编号。 8. `Fix(x, v)` 修改 x 的点权为 v。 9. `Split(x, y)` 提取出 x, y 间的路径,方便做区间操作。 3. `Update(x)` 在 `Access` 操作之后,递归地从上到下 `Pushdown` 更新信息。 4. `MakeRoot(x)` 使 $x$ 点成为整棵辅助树的根。 5. `Link(x, y)` 在 $x, y$ 两点间连⼀一条边。 6. `Cut(x, y)` 把 $x, y$ 两点间边删掉。 7. `Find(x)` 找到 $x$ 所在的 Splay 的根节点编号。 8. `Fix(x, v)` 修改 $x$ 的点权为 $v$ 。 9. `Split(x, y)` 提取出 $x, y$ 间的路径,方便做区间操作。 ### 宏定义 Loading
docs/graph/kth-path.md +16 −14 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ using namespace std; const int maxn = 5010; const int maxm = 400010; const int inf = 2e9; int n, m, s, t, k, u, v, ww, H[maxn], cnt[maxn], ans; int n, m, s, t, k, u, v, ww, H[maxn], cnt[maxn]; int cur, h[maxn], nxt[maxm], p[maxm], w[maxm]; int cur1, h1[maxn], nxt1[maxm], p1[maxm], w1[maxm]; bool tf[maxn]; Loading Loading @@ -78,14 +78,13 @@ int main() { q.pop(); cnt[x.x]++; if (x.x == t && cnt[x.x] == k) { printf("%d\n", ans); printf("%d\n", x.v); return 0; ans++; } if (cnt[x.x] > k) continue; for (int j = h[x.x]; j; j = nxt[j]) q.push({p[j], x.v + w[j]}); } printf("%d\n", ans); printf("-1\n"); return 0; } ``` Loading Loading @@ -159,7 +158,7 @@ int main() { #include <queue> using namespace std; const int maxn = 200010; int n, m, s, t, k, x, y, ww, cnt, ans, fa[maxn]; int n, m, s, t, k, x, y, ww, cnt, fa[maxn]; struct Edge { int cur, h[maxn], nxt[maxn], p[maxn], w[maxn]; void add_edge(int x, int y, int z) { Loading Loading @@ -212,7 +211,7 @@ struct LeftistTree { } st; void dfs2(int x) { vis[x] = true; if (fa[x] && fa[x] != n) st.rt[x] = st.merge(st.rt[x], st.rt[fa[x]]); if (fa[x]) st.rt[x] = st.merge(st.rt[x], st.rt[fa[x]]); for (int j = e2.h[x]; j; j = e2.nxt[j]) if (fa[e2.p[j]] == x && !vis[e2.p[j]]) dfs2(e2.p[j]); } Loading @@ -220,7 +219,7 @@ int main() { scanf("%d%d%d%d%d", &n, &m, &s, &t, &k); for (int i = 1; i <= m; i++) scanf("%d%d%d", &x, &y, &ww), e1.add_edge(x, y, ww), e2.add_edge(y, x, ww); Q.push({n, 0}); Q.push({t, 0}); while (!Q.empty()) { a = Q.top(); Q.pop(); Loading @@ -230,10 +229,13 @@ int main() { for (int j = e2.h[a.x]; j; j = e2.nxt[j]) Q.push({e2.p[j], a.v + e2.w[j]}); } if (k == 1) { printf("%d\n", dist[1]); if (tf[s]) printf("%d\n", dist[s]); else printf("-1\n"); return 0; } dfs(n); dfs(t); for (int i = 1; i <= n; i++) if (tf[i]) for (int j = e1.h[i]; j; j = e1.nxt[j]) Loading @@ -243,8 +245,8 @@ int main() { st.rt[i], st.newnode({e1.p[j], dist[e1.p[j]] + e1.w[j] - dist[i]})); for (int i = 1; i <= n; i++) vis[i] = false; dfs2(n); if (st.rt[1]) Q.push({st.rt[1], dist[1] + st.v[st.rt[1]].v}); dfs2(t); if (st.rt[s]) Q.push({st.rt[s], dist[s] + st.v[st.rt[s]].v}); while (!Q.empty()) { a = Q.top(); Q.pop(); Loading @@ -257,10 +259,10 @@ int main() { Q.push({st.lc[a.x], a.v - st.v[a.x].v + st.v[st.lc[a.x]].v}); if (st.rc[a.x]) Q.push({st.rc[a.x], a.v - st.v[a.x].v + st.v[st.rc[a.x]].v}); int t = st.rt[st.v[a.x].x]; if (t) Q.push({t, a.v + st.v[t].v}); x = st.rt[st.v[a.x].x]; if (x) Q.push({x, a.v + st.v[x].v}); } printf("%d\n", ans); printf("-1\n"); return 0; } ``` Loading