光速乘
有用到负数用ll,没有则ull
typedef long long ll; typedef unsigned long long ull; ll mul(ll x, ll y, ll Mod) { ll res = x * y - (ll)((long double)x / Mod * y + 0.5L) * Mod; return res < 0 ? res + Mod : res; }
斐波那契数列性质
字符串匹配相关
#include <bits/stdc++.h> using namespace std; int n, mat[200010], tr[200010][26], fa[200010], nodeid; char s[2000010], t[200010]; int ins(char *str) { int u = 0; for (int i = 0; str[i]; i++) { int c = str[i] - 'a'; if (!tr[u][c]) tr[u][c] = ++nodeid; u = tr[u][c]; } return u; } queue<int> q; void build() { for (int c = 0; c < 26; c++) if (tr[0][c]) q.push(tr[0][c]); while (!q.empty()) { int u = q.front(); q.pop(); for (int c = 0; c < 26; c++) if (tr[u][c]) fa[tr[u][c]] = tr[fa[u]][c], q.push(tr[u][c]); else tr[u][c] = tr[fa[u]][c]; } } int head[200010], to[200010], nxt[200010], cnt, sze[200010]; void add_edge(int u, int v) { to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt; } void dfs(int u) { for (int i = head[u]; i; i = nxt[i]) dfs(to[i]), sze[u] += sze[to[i]]; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%s", t); mat[i] = ins(t); } build(); scanf("%s", s); for (int i = 0, u = 0; s[i]; i++) sze[u = tr[u][s[i] - 'a']]++; for (int i = 1; i <= nodeid; i++) add_edge(fa[i], i); dfs(0); for (int i = 1; i <= n; i++) printf("%d ", sze[mat[i]]); return 0; }
Z函数(exKMP)
#include <bits/stdc++.h> using namespace std; const int N = 2e7 + 10; char a[N], b[N]; int n, m, z[N], p[N]; long long ans; int main() { scanf("%s", a); n = strlen(a); scanf("%s", b); m = strlen(b); z[0] = 0; int l = 0, r = 0; for (int i = 1; i < m; i++) { if (i > r) { while (i + z[i] < m && b[i + z[i]] == b[z[i]]) z[i]++; l = i, r = i + z[i] - 1; } else { z[i] = min(z[i - l], r - i + 1); while (i + z[i] < m && b[i + z[i]] == b[z[i]]) z[i]++; if (r < i + z[i] - 1) r = i + z[i] - 1, l = i; } } ans = m + 1; for (int i = 1; i < m; i++) ans ^= (z[i] + 1ll) * (i + 1ll); cout << ans << endl; l = r = -1; for (int i = 0; i < n; i++) { if (i > r) { while (i + p[i] < n && p[i] < m && a[i + p[i]] == b[p[i]]) p[i]++; l = i, r = i + p[i] - 1; } else { p[i] = min(r - i + 1, z[i - l]); while (i + p[i] < n && p[i] < m && a[i + p[i]] == b[p[i]]) p[i]++; if (r < i + p[i] - 1) r = i + p[i] - 1, l = i; } } ans = 0; for (int i = 0; i < n; i++) ans ^= (p[i] + 1ll) * (i + 1ll); cout << ans << endl; return 0; }
回文相关
manacher
#include <bits/stdc++.h> using namespace std; int Right = -1, Mid = -1, len[22000010], ans; char ch, s[22000010]; int main() { ch = getchar(); while (ch < 'a' || ch > 'z') ch = getchar(); int siz = 0; for ( ; ; siz++) if (siz & 1) s[siz] = ch, ch = getchar(); else { s[siz] = '#'; if (ch < 'a' || ch > 'z') break; } for (int i = 0; i <= siz; i++) { len[i] = (Right > i ? min(len[Mid * 2 - i], Right - i) : 1); while (0 <= i - len[i] && i + len[i] <= siz && s[i - len[i]] == s[i + len[i]]) len[i]++; if (Right < i + len[i]) Right = i + len[i], Mid = i; if (ans < len[i]) ans = len[i]; } cout << ans - 1 << endl; return 0; }
#include <bits/stdc++.h> using namespace std; int l, las, nodeid, fa[300010], tr[300010][26], len[300010], cnt[300010]; char s[300010]; long long ans; void ins(int c, int n) { int cur = las; while (s[n - len[cur] - 1] != s[n]) cur = fa[cur]; int now = tr[cur][c]; if (!now) { now = ++nodeid; int v = fa[cur]; while (s[n - len[v] - 1] != s[n]) v = fa[v]; fa[now] = tr[v][c]; tr[cur][c] = now; // 一定要写在下面 len[now] = len[cur] + 2; } cnt[now]++, las = now; } int main() { scanf("%s", s + 1); l = strlen(s + 1); fa[0] = fa[1] = 1, len[0] = 0, len[1] = -1, nodeid = 1; for (int i = 1; i <= l; i++) ins(s[i] - 'a', i); for (int i = nodeid; i >= 2; i--) cnt[fa[i]] += cnt[i]; for (int i = 2; i <= nodeid; i++) ans = max(ans, 1ll * cnt[i] * len[i]); cout << ans << endl; return 0; }
后缀相关
SA
#include <bits/stdc++.h> using namespace std; const int N = 1e6 + 10; int n, m, tax[N], rak[N << 1], tmp[N << 1], sa[N], num, height[N]; char s[N]; //注意rak和tmp要开两倍 void rsort() { for (int i = 1; i <= m; i++) tax[i] = 0; for (int i = 1; i <= n; i++) tax[rak[i]]++; for (int i = 1; i <= m; i++) tax[i] += tax[i - 1]; for (int i = n; i >= 1; i--) sa[tax[rak[tmp[i]]]--] = tmp[i]; } void init() { for (int i = 1; i <= n; i++) rak[i] = s[i] - '0' + 1, tmp[i] = i; m = 75, rsort(); for (int len = 1, p = 0; p < n; m = p, len <<= 1) { num = 0; for (int i = n - len + 1; i <= n; i++) tmp[++num] = i; for (int i = 1; i <= n; i++) if (sa[i] > len) tmp[++num] = sa[i] - len; rsort(), swap(rak, tmp); rak[sa[1]] = p = 1; for (int i = 2; i <= n; i++) rak[sa[i]] = (tmp[sa[i]] == tmp[sa[i - 1]] && tmp[sa[i] + len] == tmp[sa[i - 1] + len] ? p : ++p); } int l = 0; for (int i = 1; i <= n; i++) { if (l) l--; int j = sa[rak[i] - 1]; while (s[i + l] == s[j + l]) l++; height[rak[i]] = l; } } int main() { scanf("%s", s + 1); n = strlen(s + 1); init(); for (int i = 1; i <= n; i++) printf("%d ", sa[i]); return 0; }
SAM
#include <bits/stdc++.h> using namespace std; const int L = 1e6 + 10, N = 2e6 + 10; int n, tax[L], ord[N], cnt[N], fa[N], tr[N][26], len[N], nodeid = 1, las = 1; char s[L]; void ins(int c) { int p = las, np = ++nodeid; len[np] = len[p] + 1, cnt[np] = 1; for ( ; p && !tr[p][c]; p = fa[p]) tr[p][c] = np; if (!p) fa[np] = 1; else { int q = tr[p][c]; if (len[q] == len[p] + 1) fa[np] = q; else { int nq = ++nodeid; len[nq] = len[p] + 1; for (int k = 0; k < 26; k++) tr[nq][k] = tr[q][k]; fa[nq] = fa[q], fa[q] = fa[np] = nq; for ( ; p && tr[p][c] == q; p = fa[p]) tr[p][c] = nq; } } las = np; } int main() { scanf("%s", s + 1); n = strlen(s + 1); for (int i = 1; i <= n; i++) ins(s[i] - 'a'); for (int i = 1; i <= nodeid; i++) tax[len[i]]++; for (int i = 1; i <= n; i++) tax[i] += tax[i - 1]; for (int i = 1; i <= nodeid; i++) ord[tax[len[i]]--] = i; long long ans = 0; for (int i = nodeid; i; i--) { int now = ord[i]; cnt[fa[now]] += cnt[now]; if (cnt[now] > 1) ans = max(ans, 1ll * cnt[now] * len[now]); } cout << ans << endl; return 0; }
广义SAM(在线)
#include <bits/stdc++.h> using namespace std; const int L = 1e6 + 10, N = 2e6 + 10; int n, fa[N], trans[N][26], len[N], nodeid = 1, las = 1; char s[L]; long long ans; void ins(int c) { int p = las; if (trans[p][c]) { int q = trans[p][c]; if (len[q] == len[p] + 1) las = q; else { int nq = ++nodeid; len[nq] = len[p] + 1; for (int k = 0; k < 26; k++) trans[nq][k] = trans[q][k]; fa[nq] = fa[q], fa[q] = nq; for ( ; p && trans[p][c] == q; p = fa[p]) trans[p][c] = nq; las = nq; } return ; } int np = ++nodeid; len[np] = len[p] + 1; for ( ; p && !trans[p][c]; p = fa[p]) trans[p][c] = np; if (!p) fa[np] = 1; else { int q = trans[p][c]; if (len[q] == len[p] + 1) fa[np] = q; else { int nq = ++nodeid; len[nq] = len[p] + 1; for (int k = 0; k < 26; k++) trans[nq][k] = trans[q][k]; fa[nq] = fa[q], fa[q] = fa[np] = nq; for ( ; p && trans[p][c] == q; p = fa[p]) trans[p][c] = nq; } } las = np; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%s", s); las = 1; for (int j = 0; s[j]; j++) ins(s[j] - 'a'); } for (int i = 2; i <= nodeid; i++) ans += len[i] - len[fa[i]]; cout << ans << endl; return 0; }
广义SAM(离线)
#include <bits/stdc++.h> using namespace std; const int N = 1e6 + 10; int n, tr[N][26], f[N], ch[N], pos[N], cnt = 1; int trans[N << 1][26], fa[N << 1], len[N << 1], nodeid = 1; char s[N]; long long ans; void ins(char *str) { int u = 1; for (int i = 0; str[i]; i++) { int c = str[i] - 'a'; if (!tr[u][c]) tr[u][c] = ++cnt, f[cnt] = u, ch[cnt] = c; u = tr[u][c]; } } queue<int> q; int ins(int c, int las) { int p = las, np = ++nodeid; len[np] = len[p] + 1; for ( ; p && !trans[p][c]; p = fa[p]) trans[p][c] = np; if (!p) fa[np] = 1; else { int q = trans[p][c]; if (len[q] == len[p] + 1) fa[np] = q; else { int nq = ++nodeid; len[nq] = len[p] + 1; for (int k = 0; k < 26; k++) trans[nq][k] = trans[q][k]; fa[nq] = fa[q], fa[np] = fa[q] = nq; for ( ; p && trans[p][c] == q; p = fa[p]) trans[p][c] = nq; } } return np; } void build() { for (int c = 0; c < 26; c++) if (tr[1][c]) q.push(tr[1][c]); pos[1] = 1; while (!q.empty()) { int u = q.front(); q.pop(); pos[u] = ins(ch[u], pos[f[u]]); for (int c = 0; c < 26; c++) if (tr[u][c]) q.push(tr[u][c]); } } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%s", s), ins(s); build(); for (int i = 2; i <= nodeid; i++) ans += len[i] - len[fa[i]]; cout << ans << endl; return 0; }
最小表示法
#include <bits/stdc++.h> using namespace std; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } inline void write(int x, char ch) { if (x < 0) putchar('-'), x = -x; if (x == 0) putchar('0'); else { int num = 0; char cc[22]; while (x) cc[++num] = x % 10 + 48, x /= 10; while (num) putchar(cc[num--]); } putchar(ch); } int n, arr[600010]; int main() { n = read(); for (int i = 1; i <= n; i++) arr[i] = arr[i + n] = read(); int u = 1, v = 2, w = 0; while (u <= n && v <= n && w < n) if (arr[u + w] == arr[v + w]) w++; else { if (arr[u + w] < arr[v + w]) v += w + 1; else u += w + 1; if (u == v) v++; w = 0; } if (u > v) swap(u, v); for (int i = u; i < u + n; i++) write(arr[i], ' '); return 0; }
LCT
#include <bits/stdc++.h> #define check(x) (tr[fa[x]][1] == x) #define isroot(x) (tr[fa[x]][0] != x && tr[fa[x]][1] != x) #define pushup(x) (sum[x] = sum[tr[x][0]] ^ sum[tr[x][1]] ^ val[x]) using namespace std; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } inline void write(int x) { if (x < 0) putchar('-'), x = -x; if (x == 0) putchar('0'); else { int num = 0; char cc[20]; while (x) cc[++num] = x % 10 + 48, x /= 10; while (num) putchar(cc[num--]); } putchar(' '); } int n, m, val[100010], tr[100010][2], sum[100010], fa[100010]; bool rev[100010]; void rotate(int x) { int y = fa[x], z = fa[y], opt1 = check(x), opt2 = check(y); if (!isroot(y)) tr[z][opt2] = x; fa[x] = z; tr[y][opt1] = tr[x][opt1 ^ 1], fa[tr[x][opt1 ^ 1]] = y; tr[x][opt1 ^ 1] = y, fa[y] = x; pushup(y), pushup(x); } inline void reverse(int x) { swap(tr[x][0], tr[x][1]), rev[x] ^= 1; } inline void pushdown(int x) { if (rev[x]) { if (tr[x][0]) reverse(tr[x][0]); if (tr[x][1]) reverse(tr[x][1]); rev[x] = 0; } } void pushall(int x) { if (!isroot(x)) pushall(fa[x]); pushdown(x); } void splay(int x) { pushall(x); while (!isroot(x)) { int y = fa[x], z = fa[y]; if (!isroot(y)) rotate(check(x) == check(y) ? y : x); rotate(x); } pushup(x); } inline void access(int x) { for (int y = 0; x; y = x, x = fa[x]) splay(x), tr[x][1] = y, pushup(x); } inline int findrt(int x) { access(x), splay(x); while (tr[x][0]) pushdown(x), x = tr[x][0]; return splay(x), x; } inline void makert(int x) { access(x), splay(x), reverse(x); } inline void link(int x, int y) { makert(x); if (findrt(y) != x) fa[x] = y; } inline void cut(int x, int y) { makert(x); if (findrt(y) == x && fa[y] == x && !tr[x][0]) fa[y] = tr[x][1] = 0, pushup(x); } inline void split(int x, int y) { makert(x), access(y), splay(y); } int main() { n = read(), m = read(); for (int i = 1; i <= n; i++) val[i] = read(); for (int i = 1; i <= m; i++) { int opt = read(), x = read(), y = read(); if (opt == 0) split(x, y), write(sum[y]); else if (opt == 1) link(x, y); else if (opt == 2) cut(x, y); else splay(x), val[x] = y; } return 0; }
网络流
最大流
#include <bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } inline void write(ll x) { if (x < 0) putchar('-'), x = -x; if (x == 0) putchar('0'); else { int num = 0; char cc[22]; while (x) cc[++num] = x % 10 + 48, x /= 10; while (num) putchar(cc[num--]); } putchar(' '); } const int N = 210, M = 5010; int n, m, s, t, head[N], nxt[M << 1], to[M << 1], edge[M << 1], cnt = 1; void add_edge(int u, int v, int w) { to[++cnt] = v; edge[cnt] = w; nxt[cnt] = head[u]; head[u] = cnt; } queue<int> q; int d[N]; bool bfs() { for (int i = 1; i <= n; i++) d[i] = 0; while (q.size()) q.pop(); q.push(s), d[s] = 1; while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (edge[i] && !d[v]) { d[v] = d[u] + 1; if (v == t) return true; q.push(v); } } } return false; } int dinic(int u, int flow) { if (u == t) return flow; int rest = flow, now; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (edge[i] && d[v] == d[u] + 1) { now = dinic(v, min(rest, edge[i])); if (!now) d[v] = 0; edge[i] -= now, edge[i ^ 1] += now; rest -= now; } } return flow - rest; } int main() { n = read(), m = read(), s = read(), t = read(); for (int i = 1; i <= m; i++) { int u = read(), v = read(), w = read(); add_edge(u, v, w), add_edge(v, u, 0); } int flow = 0; ll maxflow = 0; while (bfs()) while (flow = dinic(s, INT_MAX)) maxflow += flow; write(maxflow); return 0; }
费用流
#include <bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } inline void write(int x, char ch) { if (x < 0) putchar('-'), x = -x; if (x == 0) putchar('0'); else { int num = 0; char cc[22]; while (x) cc[++num] = x % 10 + 48, x /= 10; while (num) putchar(cc[num--]); } putchar(ch); } const int N = 5e3 + 10, M = 5e4 + 10; int n, m, s, t, ans; int head[N], to[M << 1], nxt[M << 1], edge[M << 1], cst[M << 1], cnt = 1, h[N]; void add_edge(int u, int v, int w, int c) { to[++cnt] = v, edge[cnt] = w, cst[cnt] = c; nxt[cnt] = head[u], head[u] = cnt; } int dis[N]; bool vis[N]; queue<int> q; bool spfa() { for (int i = 1; i <= n; i++) dis[i] = INT_MAX, h[i] = head[i], vis[i] = false; while (q.size()) q.pop(); dis[s] = 0, vis[s] = true, q.push(s); while (q.size()) { int u = q.front(); vis[u] = false; q.pop(); for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (edge[i] && dis[v] > dis[u] + cst[i]) { dis[v] = dis[u] + cst[i]; //if (v == t) return true; if (!vis[v]) q.push(v), vis[v] = true; } } } return dis[t] != INT_MAX; } int dinic(int u, int flow) { if (u == t) return flow; vis[u] = true; int rest = flow, now; for (int &i = h[u]; i; i = nxt[i]) { int v = to[i]; if (!vis[v] && edge[i] && dis[v] == dis[u] + cst[i]) { now = dinic(v, min(rest, edge[i])); if (now == 0) dis[v] = INT_MAX; edge[i] -= now, edge[i ^ 1] += now, rest -= now; ans += now * cst[i]; } } return flow - rest; } int main() { n = read(), m = read(), s = read(), t = read(); for (int i = 1; i <= m; i++) { int u = read(), v = read(), w = read(), c = read(); add_edge(u, v, w, c), add_edge(v, u, 0, -c); } int flow = 0, maxflow = 0; while (spfa()) while (flow = dinic(s, 5000000)) maxflow += flow; write(maxflow, ' '), write(ans, ' '); return 0; }
无源汇上下界可行流
void add_edge(int u, int v, int w) { to[++cnt] = v, edge[cnt] = w, nxt[cnt] = head[u], head[u] = cnt; } void addedge(int u, int v, int w) { add_edge(u, v, w), add_edge(v, u, 0); } queue<int> q; int d[N]; bool bfs() { while (q.size()) q.pop(); for (int i = 0; i <= t; i++) d[i] = 0, h[i] = head[i]; q.push(s), d[s] = 1; while (q.size()) { int u = q.front(); q.pop(); for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (edge[i] && !d[v]) { d[v] = d[u] + 1; if (v == t) return true; q.push(v); } } } return false; } int dinic(int u, int flow) { if (u == t) return flow; int rest = flow, now; for (int &i = h[u]; i; i = nxt[i]) { int v = to[i]; if (edge[i] && d[v] == d[u] + 1) { now = dinic(v, min(rest, edge[i])); edge[i] -= now, edge[i ^ 1] += now, rest -= now; } } return flow - rest; } int main() { n = read(), m = read(); s = 0, t = n + 1; for (int i = 1; i <= m; i++) { int u = read(), v = read(), down = read(), up = read(); outf[u] += down, inf[v] += down, dow[i] = down, addedge(u, v, up - down); } int sum = 0; for (int i = 1; i <= n; i++) { if (inf[i] > outf[i]) addedge(s, i, inf[i] - outf[i]); if (inf[i] < outf[i]) addedge(i, t, outf[i] - inf[i]); } while (bfs()) dinic(s, 0x3f3f3f3f); bool flag = false; for (int i = head[s]; i; i = nxt[i]) if (!(i & 1)) flag |= (edge[i] != 0); if (flag) puts("NO"); else { puts("YES"); for (int i = 2; i <= (m << 1); i += 2) write(dow[i >> 1] + edge[i ^ 1], ' '); } return 0; }
有源汇上下界最大流
void add_edge(int u, int v, int w) { to[++cnt] = v, edge[cnt] = w, nxt[cnt] = head[u], head[u] = cnt; } void addedge(int u, int v, int w) { add_edge(u, v, w), add_edge(v, u, 0); } queue<int> q; int d[N]; bool bfs() { while (q.size()) q.pop(); if (T != n + 1) for (int i = 1; i <= n; i++) d[i] = 0, h[i] = head[i]; else for (int i = 0; i <= T; i++) d[i] = 0, h[i] = head[i]; q.push(S), d[S] = 1; while (q.size()) { int u = q.front(); q.pop(); for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (edge[i] && !d[v]) { d[v] = d[u] + 1; if (v == T) return true; q.push(v); } } } return false; } int dinic(int u, int flow) { if (u == T) return flow; int rest = flow, now; for (int &i = h[u]; i; i = nxt[i]) { int v = to[i]; if (edge[i] && d[v] == d[u] + 1) { now = dinic(v, min(rest, edge[i])); edge[i] -= now, edge[i ^ 1] += now, rest -= now; } } return flow - rest; } int main() { scanf("%d%d%d%d", &n, &m, &s, &t); for (int i = 1; i <= m; i++) { int u, v, down, up; scanf("%d%d%d%d", &u, &v, &down, &up); f[u] -= down, f[v] += down, addedge(u, v, up - down); } S = 0, T = n + 1; for (int i = 1; i <= n; i++) { if (f[i] > 0) addedge(S, i, f[i]); if (f[i] < 0) addedge(i, T, -f[i]); } addedge(t, s, 0x3f3f3f3f); long long maxflow = 0; while (bfs()) dinic(S, 0x3f3f3f3f); for (int i = head[S]; i; i = nxt[i]) if (!(i & 1) && edge[i]) return puts("please go home to sleep"), 0; head[s] = nxt[head[s]], head[t] = nxt[head[t]]; maxflow = edge[cnt], d[S] = d[T] = -1, S = s, T = t; while (bfs()) maxflow += dinic(S, 0x3f3f3f3f); cout << maxflow << endl; return 0; }
圆方树
void tarjan(int u) { low[u] = dfn[u] = ++times, stk[++tp] = u, tot++; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (!dfn[v]) { tarjan(v); if (low[u] > low[v]) low[u] = low[v]; if (low[v] == dfn[u]) { cnt++; for (int p = 0; p != v; tp--) { val[cnt]++, p = stk[tp]; son[cnt].push_back(p); son[p].push_back(cnt); } val[cnt]++; son[cnt].push_back(u); son[u].push_back(cnt); } } else if (low[u] > dfn[v]) low[u] = dfn[v]; } } cnt = n; for (int i = 1; i <= n; i++) if (!dfn[i]) tot = 0, tarjan(i), --tp/*, dfs(i, 0)*/;
最近公共祖先
欧拉序+RMQ
#include <bits/stdc++.h> using namespace std; const int N = 5e5 + 10; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } inline void write(int x, char ch) { if (x < 0) putchar('-'), x = -x; if (x == 0) putchar('0'); else { int num = 0; char cc[22]; while (x) cc[++num] = x % 10 + 48, x /= 10; while (num) putchar(cc[num--]); } putchar(ch); } int n, m, rt, head[N], to[N << 1], nxt[N << 1], cnt; void add_edge(int u, int v) { to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt; } int e[N << 1], times, fir[N]; void dfs(int u, int fa) { e[++times] = u, fir[u] = times; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa) continue; dfs(v, u), e[++times] = u; } } int Min[20][N << 1], Log[N << 1]; void init() { Log[0] = -1; for (int i = 1; i <= times; i++) Log[i] = Log[i >> 1] + 1, Min[0][i] = fir[e[i]]; for (int k = 1; (1 << k) <= times; k++) for (int i = 1; i + (1 << k) - 1 <= times; i++) Min[k][i] = min(Min[k - 1][i], Min[k - 1][i + (1 << (k - 1))]); } int MIN(int l, int r) { int t = Log[r - l + 1]; return min(Min[t][l], Min[t][r - (1 << t) + 1]); } int main() { n = read(), m = read(), rt = read(); for (int i = 1; i < n; i++) { int u = read(), v = read(); add_edge(u, v), add_edge(v, u); } dfs(rt, 0), init(); for (int i = 1; i <= m; i++) { int u = read(), v = read(); if (fir[u] > fir[v]) swap(u, v); write(e[MIN(fir[u], fir[v])], ' '); } return 0; }
动态DP
$Theta(nlog^2n)$
#include <bits/stdc++.h> #define mul(i, j) res.g[i][j] = max(g[i][0] + p.g[0][j], g[i][1] + p.g[1][j]) #define lson u << 1, l, mid #define rson u << 1 | 1, mid + 1, r using namespace std; typedef long long ll; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } inline void write(int x, char ch) { if (x < 0) putchar('-'), x = -x; if (x == 0) putchar('0'); else { int num = 0; char cc[22]; while (x) cc[++num] = x % 10 + 48, x /= 10; while (num) putchar(cc[num--]); } putchar(ch); } inline int max(const int &g, const int &h) { return g > h ? g : h; } const int N = 1e5 + 10; struct mat { int g[2][2]; void set() { g[0][0] = g[1][1] = 0, g[0][1] = g[1][0] = -0x3f3f3f3f; } mat operator * (const mat &p) const { mat res; mul(0, 0), mul(0, 1), mul(1, 0), mul(1, 1); return res; } } s[N], tr[N << 2]; int n, m, a[N], dp[N][2]; int head[N], to[N << 1], nxt[N << 1], cnt; void add_edge(int u, int v) { to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt; } int sze[N], hea[N], dfn[N], tp[N], ed[N], f[N], id[N], times; void dfs1(int u, int fa) { sze[u] = 1, f[u] = fa, dp[u][1] = a[u]; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa) continue; dfs1(v, u), sze[u] += sze[v]; if (sze[hea[u]] < sze[v]) hea[u] = v; dp[u][1] += dp[v][0], dp[u][0] += max(dp[v][0], dp[v][1]); } } void dfs2(int u, int t) { dfn[u] = ed[t] = ++times, id[times] = u, tp[u] = t, s[u].g[1][0] = a[u]; if (hea[u]) dfs2(hea[u], t); for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == f[u] || v == hea[u]) continue; dfs2(v, v); s[u].g[1][0] += dp[v][0], s[u].g[0][0] += max(dp[v][0], dp[v][1]); } s[u].g[0][1] = s[u].g[0][0], s[u].g[1][1] = -0x3f3f3f3f; } void build(int u, int l, int r) { if (l == r) tr[u] = s[id[l]]; else { int mid = (l + r) >> 1; build(lson), build(rson); tr[u] = tr[u << 1] * tr[u << 1 | 1]; } } mat query(int u, int l, int r, int Left, int Right) { if (Left <= l && r <= Right) return tr[u]; int mid = (l + r) >> 1; mat res; res.set(); if (Left <= mid) res = res * query(lson, Left, Right); if (mid < Right) res = res * query(rson, Left, Right); return res; } void modify(int u, int l, int r, int pos) { if (l == r) tr[u] = s[id[l]]; else { int mid = (l + r) >> 1; if (pos <= mid) modify(lson, pos); else modify(rson, pos); tr[u] = tr[u << 1] * tr[u << 1 | 1]; } } void updata(int x, int y) { s[x].g[1][0] += y - a[x], a[x] = y; while (x) { mat las = query(1, 1, n, dfn[tp[x]], ed[tp[x]]); modify(1, 1, n, dfn[x]); mat now = query(1, 1, n, dfn[tp[x]], ed[tp[x]]); x = f[tp[x]]; s[x].g[0][0] += max(now.g[0][0], now.g[1][0]) - max(las.g[0][0], las.g[1][0]); s[x].g[1][0] += now.g[0][0] - las.g[0][0]; s[x].g[0][1] = s[x].g[0][0]; } } int main() { n = read(), m = read(); for (int i = 1; i <= n; i++) a[i] = read(); for (int i = 1; i < n; i++) { int u = read(), v = read(); add_edge(u, v), add_edge(v, u); } dfs1(1, 0), dfs2(1, 1), build(1, 1, n); for (int i = 1; i <= m; i++) { int x = read(), y = read(); updata(x, y); mat ans = query(1, 1, n, dfn[1], ed[1]); write(max(ans.g[0][0], ans.g[1][0]), ' '); } return 0; }
$Theta(nlog n)$
#include <bits/stdc++.h> #define mul(i, j) res.g[i][j] = max(g[i][0] + p.g[0][j], g[i][1] + p.g[1][j]) #define isroot(u) (ls[f[u]] != u && rs[f[u]] != u) using namespace std; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } inline void write(int x, char ch) { if (x < 0) putchar('-'), x = -x; if (x == 0) putchar('0'); else { int num = 0; char cc[22]; while (x) cc[++num] = x % 10 + 48, x /= 10; while (num) putchar(cc[num--]); } putchar(ch); } inline int max(const int &g, const int &h) { return g > h ? g : h; } const int N = 1e6 + 10; int n, m, val[N], root, f[N], ls[N], rs[N], lasans; int head[N], to[N << 1], nxt[N << 1], cnt; void add_edge(int u, int v) { to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt; } struct Matrix { int g[2][2]; Matrix operator * (const Matrix p) const { Matrix res; mul(0, 0), mul(0, 1), mul(1, 0), mul(1, 1); return res; } } dat[N], mat[N]; int sze[N], lsze[N], hea[N], dp[N][2], id[N], pre[N], tot; void pushup(int u) { mat[u] = dat[u]; if (ls[u]) mat[u] = mat[ls[u]] * mat[u]; if (rs[u]) mat[u] = mat[u] * mat[rs[u]]; } void dfs1(int u, int fa) { sze[u] = lsze[u] = 1, dp[u][1] = val[u]; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa) continue; dfs1(v, u), sze[u] += sze[v]; if (sze[hea[u]] < sze[v]) hea[u] = v; } for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa || v == hea[u]) continue; dp[u][0] += max(dp[v][0], dp[v][1]); dp[u][1] += dp[v][0], lsze[u] += lsze[v]; } dat[u].g[0][0] = dat[u].g[0][1] = dp[u][0]; dat[u].g[1][0] = dp[u][1], dat[u].g[1][1] = -0x3f3f3f3f; dp[u][0] += max(dp[hea[u]][0], dp[hea[u]][1]); dp[u][1] += dp[hea[u]][0]; } int build(int l, int r) { int mid = lower_bound(pre + l, pre + r + 1, (pre[l - 1] + pre[r]) >> 1) - pre, u = id[mid]; if (l < mid) f[ls[u] = build(l, mid - 1)] = u; if (mid < r) f[rs[u] = build(mid + 1, r)] = u; pushup(u); return u; } void updata(int u) { Matrix las = mat[u]; pushup(u); int fa = f[u]; if (fa && isroot(u)) { Matrix now = mat[u]; dat[fa].g[0][1] = (dat[fa].g[0][0] += max(now.g[0][0], now.g[1][0]) - max(las.g[0][0], las.g[1][0])); dat[fa].g[1][0] += now.g[0][0] - las.g[0][0]; } if (fa) updata(fa); } int dfs2(int u, int fa) { //cout << u << " " << fa << endl; id[++tot] = u, pre[tot] = pre[tot - 1] + lsze[u]; int rt; if (hea[u]) rt = dfs2(hea[u], u); else return build(1, tot); for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa || v == hea[u]) continue; tot = 0, f[dfs2(v, u)] = u; } return rt; } int main() { n = read(), m = read(); for (int i = 1; i <= n; i++) val[i] = read(); for (int i = 1; i < n; i++) { int u = read(), v = read(); add_edge(u, v), add_edge(v, u); } dfs1(1, 0), root = dfs2(1, 0); for (int i = 1; i <= m; i++) { int x = read() ^ lasans, y = read(); dat[x].g[1][0] += y - val[x], val[x] = y; updata(x); write(lasans = max(mat[root].g[0][0], mat[root].g[1][0]), ' '); } return 0; }
虚树
void ins(int x) { if (tp <= 1) return stk[++tp] = x, void(); int lca = Lca(x, stk[tp]); if (lca != stk[tp]) { while (tp > 1 && dfn[lca] <= dfn[stk[tp - 1]]) son[stk[tp - 1]].push_back(stk[tp]), tp--; if (lca != stk[tp]) son[lca].push_back(stk[tp]), stk[tp] = lca; } stk[++tp] = x; } sort(id + 1, id + m + 1, cmp); tp = 0; if (id[1] != 1) stk[tp = 1] = 1; for (int i = 1; i <= m; i++) ins(id[i]); while (tp > 1) son[stk[tp - 1]].push_back(stk[tp]), tp--;
2-sat及构造解
#include <bits/stdc++.h> using namespace std; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } inline void write(int x, char ch) { if (x < 0) putchar('-'), x = -x; if (x == 0) putchar('0'); else { int num = 0; char cc[22]; while (x) cc[++num] = x % 10 + 48, x /= 10; while (num) putchar(cc[num--]); } putchar(ch); } const int N = 1e6 + 10; int n, m, head[N << 1], to[N << 1], nxt[N << 1], cnt; void add_edge(int u, int v) { to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt; } int dfn[N << 1], low[N << 1], times, stk[N << 1], tp, id[N << 1], tot; bool ins[N << 1]; void tarjan(int u) { dfn[u] = low[u] = ++times; stk[++tp] = u, ins[u] = true; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (!dfn[v]) { tarjan(v); if (low[u] > low[v]) low[u] = low[v]; } else if (ins[v] && low[u] > dfn[v]) low[u] = dfn[v]; } if (dfn[u] == low[u]) { tot++; int v; do { v = stk[tp--], ins[v] = false, id[v] = tot; } while (u != v); } } int main() { n = read(), m = read(); for (int i = 1; i <= m; i++) { int x = read(), a = read(), y = read(), b = read(); add_edge(x + (((a ^ 1) & 1) ? n : 0), y + ((b & 1) ? n : 0)); add_edge(y + (((b ^ 1) & 1) ? n : 0), x + ((a & 1) ? n : 0)); } for (int i = 1; i <= (n << 1); i++) if (!dfn[i]) tarjan(i); for (int i = 1; i <= n; i++) if (id[i] == id[n + i]) return puts("IMPOSSIBLE"), 0; puts("POSSIBLE"); for (int i = 1; i <= n; i++) write(id[n + i] < id[i], ' '); return 0; }
欧拉回路
左偏树
#include <bits/stdc++.h> using namespace std; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } inline void write(int x, char ch) { if (x < 0) putchar('-'), x = -x; if (x == 0) putchar('0'); else { int num = 0; char cc[22]; while (x) cc[++num] = x % 10 + 48, x /= 10; while (num) putchar(cc[num--]); } putchar(ch); } const int N = 1e5 + 10; int n, m, val[N], dis[N], fa[N], ls[N], rs[N]; bool del[N]; int find(int u) { return fa[u] == u ? u : fa[u] = find(fa[u]); } int merge(int x, int y) { if (!x || !y) return x | y; if (val[x] > val[y] || (val[x] == val[y] && x > y)) swap(x, y); rs[x] = merge(rs[x], y); if (dis[ls[x]] < dis[rs[x]]) swap(ls[x], rs[x]); dis[x] = dis[rs[x]] + 1; return x; } int main() { n = read(), m = read(); for (int i = 1; i <= n; i++) val[i] = read(), fa[i] = i; for (int i = 1; i <= m; i++) { int opt = read(); if (opt == 1) { int x = read(), y = read(); if (del[x] || del[y]) continue; x = find(x), y = find(y); if (x != y) fa[x] = fa[y] = merge(x, y); } else { int x = read(); if (del[x]) puts("-1"); else { x = find(x), del[x] = true, write(val[x], ' '); if (!ls[x] && !rs[x]) continue; if (!rs[x]) fa[x] = fa[ls[x]] = ls[x]; else fa[ls[x]] = fa[rs[x]] = fa[x] = merge(ls[x], rs[x]); } } } return 0; }
笛卡尔树
#include <bits/stdc++.h> using namespace std; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } const int N = 1e7 + 10; int n, val[N], stk[N], tp, cur, ls[N], rs[N]; long long ansl, ansr; int main() { n = read(); for (int i = 1; i <= n; i++) { val[i] = read(); cur = tp; while (cur && val[stk[cur]] > val[i]) cur--; if (cur) rs[stk[cur]] = i; if (cur < tp) ls[i] = stk[cur + 1]; tp = cur, stk[++tp] = i; } for (int i = 1; i <= n; i++) ansl ^= (ls[i] + 1ll) * i, ansr ^= (rs[i] + 1ll) * i; printf("%lld %lld ", ansl, ansr); return 0; }
点分治
#include <bits/stdc++.h> using namespace std; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } const int N = 1e4 + 10; int n, m, k, que[110], rt, sze[N], Max[N], sum; bool ans[110]; int head[N], to[N << 1], nxt[N << 1], edge[N << 1], cnt; void add_edge(int u, int v, int w) { to[++cnt] = v, edge[cnt] = w, nxt[cnt] = head[u], head[u] = cnt; } bool vis[N], p[10000010]; int dis[N], stk[N], tp; void calc(int u, int fa) { sze[u] = 1, Max[u] = 0; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa || vis[v]) continue; calc(v, u), sze[u] += sze[v]; if (Max[u] < sze[v]) Max[u] = sze[v]; } if (Max[u] < sum - sze[u]) Max[u] = sum - sze[u]; if (Max[rt] > Max[u]) rt = u; } void add(int u, int fa) { if (dis[u] <= 10000000) stk[++tp] = dis[u]; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa || vis[v]) continue; dis[v] = dis[u] + edge[i], add(v, u); } } void clean(int u, int fa) { if (dis[u] <= 10000000) p[dis[u]] = false; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa || vis[v]) continue; clean(v, u); } } void dfs(int u, int fa) { //cout << u << ',' << fa << endl; vis[u] = p[dis[u] = 0] = true; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa || vis[v]) continue; dis[v] = edge[i], add(v, u); //cout << v << " " << tp << endl; //cout << stk[tp] << " " << dis[stk[tp]] << " " << edge[i] << endl; for (int j = 1; j <= tp; j++) for (int k = 1; k <= m; k++) if (que[k] >= stk[j]) ans[k] |= p[que[k] - stk[j]]; while (tp > 0) p[stk[tp--]] = true; } clean(u, fa); for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa || vis[v]) continue; sum = sze[v], Max[rt = 0] = 0x3f3f3f3f, calc(v, u), calc(rt, 0), dfs(rt, u); } } int main() { n = read(), m = read(); for (int i = 1; i < n; i++) { int u = read(), v = read(), w = read(); add_edge(u, v, w), add_edge(v, u, w); } for (int i = 1; i <= m; i++) que[i] = read(); sum = n, Max[0] = 0x3f3f3f3f, calc(1, 0), calc(rt, 0), dfs(rt, 0); for (int i = 1; i <= m; i++) puts(ans[i] ? "AYE" : "NAY"); return 0; }
点分树
#include <bits/stdc++.h> typedef long long ll; using namespace std; inline int read() { int out = 0; bool flag = false; register char cc = getchar(); while (cc < '0' || cc > '9') { if (cc == '-') flag = true; cc = getchar(); } while (cc >= '0' && cc <= '9') { out = (out << 3) + (out << 1) + (cc ^ 48); cc = getchar(); } return flag ? -out : out; } inline void write(int x, char ch) { if (x < 0) putchar('-'), x = -x; if (x == 0) putchar('0'); else { int num = 0; char cc[22]; while (x) cc[++num] = x % 10 + 48, x /= 10; while (num) putchar(cc[num--]); } putchar(ch); } const int N = 1e5 + 10, MAXN = 8e6 + 10; int n, m, val[N], las; int head[N], to[N << 1], nxt[N << 1], cnt; void add_edge(int u, int v) { to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt; } int dep[N], e[N << 1], fir[N], times, Min[18][N << 1], Log[N << 1]; void pre(int u, int fa) { e[++times] = u, fir[u] = times, dep[u] = dep[fa] + 1; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa) continue; pre(v, u), e[++times] = u; } } void init() { Log[0] = -1; for (int i = 1; i <= times; i++) Log[i] = Log[i >> 1] + 1, Min[0][i] = fir[e[i]]; for (int k = 1; (1 << k) <= times; k++) { for (int i = 1; i + (1 << k) - 1 <= times; i++) Min[k][i] = min(Min[k - 1][i], Min[k - 1][i + (1 << (k - 1))]); } } int Lca(int x, int y) { x = fir[x], y = fir[y]; if (x > y) swap(x, y); int t = Log[y - x + 1]; return e[min(Min[t][x], Min[t][y - (1 << t) + 1])]; } vector<int> son[N]; int sze[N], Max[N], sum, rt, f[N]; bool vis[N]; void calc(int u, int fa) { sze[u] = 1, Max[u] = 0; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa || vis[v]) continue; calc(v, u), sze[u] += sze[v]; if (Max[u] < sze[v]) Max[u] = sze[v]; } if (Max[u] < sum - sze[u]) Max[u] = sum - sze[u]; if (Max[rt] > Max[u]) rt = u; } void calc(int u) { sze[u] = 1; for (auto v : son[u]) calc(v), sze[u] += sze[v]; } int dfs(int u, int fa) { vis[u] = true; for (int i = head[u]; i; i = nxt[i]) { int v = to[i]; if (v == fa || vis[v]) continue; sum = sze[u], rt = 0, calc(v, u), calc(rt, 0); son[u].push_back(rt), f[rt] = u; dfs(rt, u); } return u; } int root[N], ls[MAXN], rs[MAXN], nodeid, s[MAXN], frt[N]; #define lson ls[u], l, mid #define rson rs[u], mid + 1, r void modify(int &u, int l, int r, int pos, int delta) { if (!u) u = ++nodeid; if (l == r) s[u] += delta; else { int mid = (l + r) >> 1; if (pos <= mid) modify(lson, pos, delta); else modify(rson, pos, delta); s[u] = s[ls[u]] + s[rs[u]]; } } int query(int u, int l, int r, int Left, int Right) { if (Left <= l && r <= Right) return s[u]; int mid = (l + r) >> 1, res = 0; if (ls[u] && Left <= mid) res += query(lson, Left, Right); if (rs[u] && mid < Right) res += query(rson, Left, Right); return res; } void build(int u, int p) { modify(root[p], 0, sze[p] - 1, dep[u] + dep[p] - (dep[Lca(u, p)] << 1), val[u]); if (f[p]) modify(frt[p], 0, sze[p], dep[u] + dep[f[p]] - (dep[Lca(u, f[p])] << 1), val[u]); for (auto v : son[u]) build(v, p); } int main() { //freopen("1.in", "r", stdin); //freopen("1.out", "w", stdout); n = read(), m = read(); for (int i = 1; i <= n; i++) val[i] = read(); for (int i = 1; i < n; i++) { int u = read(), v = read(); add_edge(u, v), add_edge(v, u); } pre(1, 0), init(); sum = n, Max[rt = 0] = 0x3f3f3f3f; calc(1, 0), calc(rt, 0), rt = dfs(rt, 0); calc(rt); for (int i = 1; i <= n; i++) build(i, i); for ( ; m; m--) { int op = read(), x = read() ^ las, y = read() ^ las; if (op == 0) { las = query(root[x], 0, sze[x] - 1, 0, y); int u = f[x], v = x; while (u) { int dis = dep[u] + dep[x] - (dep[Lca(u, x)] << 1); if (dis > y) { v = u, u = f[u]; continue; } las -= query(frt[v], 0, sze[v], 0, y - dis); las += query(root[u], 0, sze[u] - 1, 0, y - dis); v = u, u = f[u]; } write(las, ' '); } else { int u = x; while (u) { modify(root[u], 0, sze[u] - 1, dep[u] + dep[x] - (dep[Lca(u, x)] << 1), y - val[x]); if (f[u]) modify(frt[u], 0, sze[u], dep[f[u]] + dep[x] - (dep[Lca(f[u], x)] << 1), y - val[x]); u = f[u]; } val[x] = y; } } return 0; }
单纯形
#include <bits/stdc++.h> #define eps 1e-6 #define inf 1e9 using namespace std; const int N = 1e3 + 10, M = 1e4 + 10; int n, m; double a[M][N], b[N], c[M], v; void pivot(int l, int e) { c[l] /= a[l][e]; for (int j = 1; j <= n; j++) if (j != e) a[l][j] /= a[l][e]; a[l][e] = 1.0 / a[l][e]; for (int i = 1; i <= m; i++) if (i != l && fabs(a[i][e]) > eps) { c[i] -= c[l] * a[i][e]; for (int j = 1; j <= n; j++) if (j != e) a[i][j] -= a[l][j] * a[i][e]; a[i][e] *= -a[l][e]; } v += b[e] * c[l]; for (int j = 1; j <= n; j++) if (j != e) b[j] -= b[e] * a[l][j]; b[e] *= -a[l][e]; } double simplex() { while (true) { int e = -1, l = -1; for (int j = 1; j <= n; j++) if (b[j] > eps) { e = j; break; } if (e == -1) return v; double tmp = inf; for (int i = 1; i <= m; i++) if (a[i][e] > eps && c[i] / a[i][e] < tmp) l = i, tmp = c[i] / a[i][e]; if (l == -1) return inf; pivot(l, e); } } int main() { scanf("%d%d", &n, &m); for (int j = 1; j <= n; j++) scanf("%lf", &b[j]); for (int i = 1; i <= m; i++) { int l, r; scanf("%d%d%lf", &l, &r, &c[i]); for (int j = l; j <= r; j++) a[i][j] = 1; } printf("%d", (int)(simplex() + 0.5)); return 0; }