#define x first #define y second #define endl '\n'
usingnamespace std;
using ll = longlong; using i128 = __int128; using PII = pair<int, int>; using PLI = pair<ll, int>; using PIL = pair<int, ll>; using PLL = pair<ll, ll>;
constexprint mod = 1e9 + 7; // constexpr int mod = 998244353;
i128 read(){i128 x = 0, f = 1;char ch = getchar();while (ch < '0' || ch > '9'){if (ch == '-') f = -1;ch = getchar();}while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;} voidprint(i128 x){if (x < 0){putchar('-');x = -x;}if (x > 9) print(x / 10);putchar(x % 10 + '0');} ll qmi(ll a, int b){ll res = 1;while (b){if (b & 1) res = res * a % mod;b >>= 1;a = a * a % mod;}return res;}
vector<int> add(vector<int> a, vector<int> b)//倒进倒出 { vector<int> c; int t = 0;
for (int i = 0; i < a.size() || i < b.size(); i++) { if (i < a.size()) t += a[i]; if (i < b.size()) t += b[i]; c.push_back(t % 10); t /= 10; } if (t) c.push_back(t); while (c.size() > 1 && !c.back()) c.pop_back();
boolcmp(vector<int> a, vector<int> b)//倒进倒出 { if (a.size() != b.size()) return a.size() > b.size(); for (int i = a.size() - 1; i >= 0; i--) if (a[i] != b[i]) return a[i] > b[i]; returntrue; }
vector<int> sub(vector<int> a, vector<int> b) { vector<int> c; for (int i = 0, t = 0; i < a.size(); i++) { t = a[i] - (t < 0); if (i < b.size()) t -= b[i]; c.push_back((t + 10) % 10); } while (c.size() > 1 && !c.back()) c.pop_back();
return c; }
高精度乘法
大乘小
1 2 3 4 5 6 7 8 9 10 11 12 13 14
vector<int> mul(vector<int> &a, int b)//倒进倒出 { vector<int> c; int t = 0; for (int i = 0; i < a.size() || t; i++) { if (i < a.size()) t += a[i] * b; c.push_back(t % 10); t /= 10; } while (c.size() > 1 && c.back() == 0) c.pop_back();
vector<int> div(vector<int> a, int b, int &r)//倒进倒出 { vector<int> c; r = 0; for (int i = a.size() - 1; i >= 0; i--) { r = r * 10 + a[i]; c.push_back(r / b); r %= b; } reverse(c.begin(), c.end()); while (c.size() > 1 && c.back() == 0) c.pop_back(); return c; }
二维前缀和
1 2 3 4 5 6 7 8 9 10 11 12
intmain() { for (int i = 1; i <= n; i++) //把s处理成前缀和矩阵 for (int j = 1; j <= m; j++) s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
intmain() { for (int i = 1; i <= n; i++) b[i] = a[i]; sort(b + 1, b + 1 + n);
int bn = unique(b + 1, b + 1 + n) - b - 1; for (int i = 1; i <= n; i++) { int l = 1, r = bn; while (l < r) { int mid = l + r >> 1; if (b[mid] < a[i]) l = mid + 1; else r = mid; } a[i] = l; } return0; }
区间合并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
vector<PII> merge() { sort(a, a + n);
vector<PII> res; int st = -2e9, ed = -2e9; for (int i = 0; i < n; i++) { if (ed < a[i].x) { if (st != -2e9) res.push_back({st, ed}); st = a[i].x, ed = a[i].y; } else ed = max(ed, a[i].y); } if (st != -2e9) res.push_back({st, ed});
return res; }
st表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
intmain() { cin >> n >> m; for (int i = 1; i <= n; i++) cin >> f[i][0];
for (int j = 1; j <= 20; j++) for (int i = 1; i + (1 << j) - 1 <= n; i++) f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]); //初始化
while (m--) { int l, r; cin >> l >> r; int k = log2(r - l + 1); cout << max(f[l][k], f[r - (1 << k) + 1][k]) << endl; //查询 } return0; }
intmain() { ne[0] = -1; for (int i = 1, j = -1; i < n; i++) //初始化 { while (j != -1 && p[i] != p[j + 1]) j = ne[j]; if (p[i] == p[j + 1]) j++; ne[i] = j; }
for (int i = 0, j = -1; i < m; i++) { while (j != -1 && s[i] != p[j + 1]) j = ne[j]; if (s[i] == p[j + 1]) j++; if (j == n - 1) { cout << i - j << ' '; //匹配位置的起点,从0开始 j = ne[j]; } }
return0; }
单调队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14
deque<int> q;
intmain() { for (int i = 0; i < n; i++) //窗口最小值 { while (q.size() && a[q.back()] >= a[i]) q.pop_back(); while (q.size() && i - k + 1 > q.front()) q.pop_front(); q.push_back(i); if (i >= k - 1) cout << a[q.front()] << ' '; }
return0; }
单调栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14
stack<int> s;
intmain() { for (int i = 0; i < n; i++) //左边第一个比它小的值 { while (s.size() && s.top() >= a[i]) s.pop(); if (s.size()) cout << s.top() << ' '; else cout << "-1 "; s.push(a[i]); }
int root[N], tot; int ls[N * 25], rs[N * 25], val[N * 25];
voidbuild(int &u, int l, int r)//建树 { u = ++tot; if (l == r) val[u] = a[l]; else { int mid = l + r >> 1; build(ls[u], l, mid); build(rs[u], mid + 1, r); } }
voidmodify(int &u, int v, int l, int r, int p, int x)//把位置p的值修改为x { u = ++tot; ls[u] = ls[v], rs[u] = rs[v], val[u] = val[v]; if (l == r) val[u] = x; else { int mid = l + r >> 1; if (p <= mid) modify(ls[u], ls[v], l, mid, p, x); elsemodify(rs[u], rs[v], mid + 1, r, p, x); } }
intquery(int u, int l, int r, int p)//查询 { if (l == r) return val[u]; int mid = l + r >> 1; if (p <= mid) returnquery(ls[u], l, mid, p); elsereturnquery(rs[u], mid + 1, r, p); }
int n, m; int a[N], b[N]; int root[N], tot; int ls[N * 25], rs[N * 25], sum[N * 25];
voidmodify(int &u, int v, int l, int r, int p) { u = ++tot; ls[u] = ls[v], rs[u] = rs[v], sum[u] = sum[v] + 1; if (l == r) return; int mid = l + r >> 1; if (p <= mid) modify(ls[u], ls[v], l, mid, p); elsemodify(rs[u], rs[v], mid + 1, r, p); }
intquery(int u, int v, int l, int r, int k)//查询区间第k小 { if (l == r) return l; int s = sum[ls[u]] - sum[ls[v]]; int mid = l + r >> 1; if (k <= s) returnquery(ls[u], ls[v], l, mid, k); elsereturnquery(rs[u], rs[v], mid + 1, r, k - s); }
intquery(int u, int v, int l, int r, int k)//查询区间比k小的个数 { if (l == r) return sum[u] - sum[v]; int mid = l + r >> 1; int res = 0; if (k <= mid) res += query(ls[u], ls[v], l, mid, k); else { res += sum[ls[u]] - sum[ls[v]]; res += query(rs[u], rs[v], mid + 1, r, k); } return res; }
intmain() { cin >> n >> m; for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) b[i] = a[i]; sort(b + 1, b + 1 + n);
int bn = unique(b + 1, b + 1 + n) - b - 1; for (int i = 1; i <= n; i++) { int l = 1, r = bn; while (l < r) { int mid = l + r >> 1; if (b[mid] < a[i]) l = mid + 1; else r = mid; } modify(root[i], root[i - 1], 1, bn, l); }
while (m--) { int l, r, k; cin >> l >> r >> k; int p = query(root[r], root[l - 1], 1, bn, k); cout << b[p] << endl; }
structTrie { int idx, cnt; int rt[N], p[N * 35][2], sz[N * 35]; voidinit(){idx = cnt = 0;} voidinsert(int v) { rt[++idx] = ++cnt; int x = rt[idx - 1], y = rt[idx]; for (int i = 30; i >= 0; i--) { int j = v >> i & 1; p[y][!j] = p[x][!j]; p[y][j] = ++cnt; x = p[x][j], y = p[y][j]; sz[y] = sz[x] + 1; } } intquery(int l, int r, int v) { int x = rt[l], y = rt[r], res = 0; for (int i = 30; i >= 0; i--) { int j = v >> i & 1; if (sz[p[y][!j]] - sz[p[x][!j]]) { res += 1 << i; x = p[x][!j], y = p[y][!j]; } else x = p[x][j], y = p[y][j]; } return res; } }T;
structQ { int id, l, r; }q[N]; int n, m, k; int b, sum; int a[N], c[N];
boolcmp(Q A, Q B) { if (A.l / b != B.l / b) return A.l < B.l; if (A.l / b & 1) return A.r < B.r; return A.r > B.r; }
voidadd(int x)//添加 { c[x]++; }
voiddel(int x)//删除 { c[x]--; }
intmain() { cin >> n >> m >> k; for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= m; i++) //离线查询 { int l, r; cin >> l >> r; q[i] = {i, l, r}; }
b = sqrt(n); sort(q + 1, q + 1 + m, cmp);
for (int i = 1, l = 1, r = 0; i <= m; i++) //查询区间每个数的出现次数 { while (l > q[i].l) add(a[--l]); while (r < q[i].r) add(a[++r]); while (l < q[i].l) del(a[l++]); while (r > q[i].r) del(a[r--]); } return0; }
booldfs(int u, int c) { color[u] = c; for (int i = 0; i < h[u].size(); i++) { int j = h[u][i]; if (!color[j]) { if (!dfs(j, 3 - c)) returnfalse; } elseif (color[j] == c) returnfalse; }
returntrue; }
intmain() { cin >> n >> m; while (m--) { int a, b; cin >> a >> b; h[a].push_back(b), h[b].push_back(a); }
bool flag = true; for (int i = 1; i <= n; i++) { if (!color[i]) { if (!dfs(i, 1)) { flag = false; break; } } }
intmain() { cin >> n >> m; while (m--) { int u, a, v, b; cin >> u >> a >> v >> b; h[u + !a * n].push_back(v + b * n); h[v + !b * n].push_back(u + a * n); }
for (int i = 1; i <= n * 2; i++) if (!dfn[i]) tarjan(i);
bool flag = false; for (int i = 1; i <= n; i++) if (scc[i] == scc[i + n]) { flag = true; break; } if (flag) cout << "IMPOSSIBLE" << endl; else { cout << "POSSIBLE" << endl; for (int i = 1; i <= n; i++) cout << (scc[i] > scc[i + n]) << ' '; }
return0; }
数学
线性筛质数
1 2 3 4 5 6 7 8 9 10 11 12
voidget_prime(int n) { for (int i = 2; i <= n; i++) { if(!st[i]) prime[cnt++] = i; for (int j = 0; prime[j] <= n / i; j++) { st[prime[j] * i] = true; if (i % prime[j] == 0) break; } } }
intexgcd(int a, int b, int &x, int &y) { if (!b) { x = 1, y = 0; return a; } else { int x1 = 0, y1 = 0; int d = exgcd(b, a % b, x1, y1); x = y1, y = x1 - a / b * y1; return d; } } // (x / d % b + b) % b x的最小非负整数解
intgauss() { int r = 0; for (int i = 0; i < n; i++) { int t = r; for (int j = r; j < n; j++) if (a[j][i] > a[t][i]) t = j;
if (!a[t][i]) continue;
if (t != r) swap(a[t], a[r]);
for (int j = r + 1; j < n; j++) if (a[j][i]) for (int k = n; k >= i; k--) a[j][k] ^= a[r][k];
r++; }
if (r < n) { for (int i = r; i < n; i++) if (a[i][n]) return0; return2; }
for (int i = n - 1; i >= 0; i--) for (int j = i + 1; j <= n; j++) a[i][n] ^= a[i][j] * a[j][n];
return1; }
组合数I
1 2 3 4 5 6 7 8 9
voidinit() { for (int i = 0; i < N; i++) for (int j = 0; j <= i; j++) { if (!j) c[i][j] = 1; else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; } }
组合数II
1 2 3 4 5 6 7 8 9 10 11 12
voidinit() { f[0] = 1; for (int i = 1; i <= N; i++) f[i] = (ll)f[i - 1] * i % mod; inv[N] = qmi(f[N], mod - 2); for (int i = N - 1; i >= 0; i--) inv[i] = (ll)inv[i + 1] * (i + 1) % mod; } intC(int a, int b) { if (a < b) return0; return (ll)f[a] * inv[b] % mod * inv[a - b] % mod; }
ll calc(int a, int b) { ll res = 0; for (int i = 0; i <= b; i++) { //inv[]:阶乘的逆元 ll sum = qmi(mod - 1, b - i) * qmi(i, a) % mod); sum = sum * inv[i] % mod * inv[b - i] % mod; res = (res + sum) % mod; } return res; }
intmain() { cin >> n; for (int i = 0; i < n; i++) cin >> a[i];
int len = 0; for(int i = 0; i < n; i++) //严格单调递增 { int l = 0, r = len; while(l < r) { int mid = l + r + 1 >> 1; if (q[mid] < a[i]) l = mid; else r = mid - 1; } len = max(len, r + 1); q[r + 1] = a[i]; }
intmain() { cin >> n >> m; cin >> k; s = ' ' + k; cin >> k; p = ' ' + k; for (int i = m; i; i--) c[p[i] - 'a'].push_back(i); for (int i = 1; i <= n; i++) for (int j = 0; j < c[s[i] - 'a'].size(); j++) w.push_back(c[s[i] - 'a'][j]); for (int i = 0; i < w.size(); i++) { int l = 0, r = len; while (l < r) { int mid = l + r + 1 >> 1; if (q[mid] < w[i]) l = mid; else r = mid - 1; } q[r + 1] = w[i]; len = max(len, r + 1); } cout << len << endl; return0; }
intdp(int u, int cnt, int op) { if (u == -1) return cnt == k; if (!op && ~f[u][cnt]) return f[u][cnt];
int res = 0, maxv = op? min(1, num[u]) : 1; for (int i = 0; i <= maxv; i++) { if (cnt + i > k) continue; res += dp(u - 1, cnt + i, op && i == num[u]); }
doublegetDP2(Point a, Point b, Point &pa, Point & pb) { Point e = getNode(a, b - a, o, rotate(b - a, PI / 2)); //垂足 double d = dis(o, e); if(!onseg(e, a, b)) d = min(dis(o, a), dis(o, b)); if(R <= d) return d; //线段在圆外 double len = sqrt(R * R - dis(o, e) * dis(o, e)); pa = e + norm(a - b) * len; pb = e + norm(b - a) * len; //pa,pb:线段与圆的两交点 return d; //d:圆心到线段的最近距离 }
doublesector(Point a, Point b)//扇形面积 { double angle = acos((a & b) / len(a) / len(b)); //[0,Pi] if(a * b < 0) angle = -angle; return R * R * angle / 2; }
doublegetArea(Point a, Point b)//面积的交 { if(fabs(a * b) < eps) return0; //共线 double da = dis(o, a), db = dis(o, b); if(R >= da && R >= db) return a * b / 2; //ab在圆内 Point pa, pb; double d = getDP2(a,b,pa,pb); //d:圆心到线段的最近距离 if(R <= d) returnsector(a,b); //ab在圆外 if(R >= da) return a*pb/2+sector(pb,b); //a在圆内 if(R >= db) returnsector(a, pa) + pa * b / 2; //b在圆内 returnsector(a, pa) + pa * pb / 2 + sector(pb, b); //ab是割线 }
structBit { int s[N], n; voidinit(int len) { n = len; for (int i = 0; i <= len; i++) s[i] = 0; } intlowbit(int x) { return x & -x; } voidmodify(int x, int k) { while (x <= n) { s[x] += k; x += lowbit(x); } } intquery(int x) { int res = 0; while (x) { res += s[x]; x -= lowbit(x); } return res; } }T;
voidsolve() { int n, m; cin >> n >> m;
T.init(n);
vector<int> a(n + 1); for (int i = 1; i <= n; i++) cin >> a[i];
structNode { int x, id, st; }; vector<vector<Node>> t(n + 1); for (int i = 0; i < m; i++) { int l, r, x; cin >> l >> r >> x; t[l - 1].push_back({x, i, -1}); t[r].push_back({x, i, 1}); }
vector<int> res(m); for (int i = 1; i <= n; i++) { T.modify(a[i], 1); for (auto [x, id, st]: t[i]) res[id] += T.query(x) * st; }
ll res = 0; for (int i = 0; i < n * 2; i++) { int l = lower_bound(s.begin(), s.end(), t[i].x1) - s.begin(); int r = lower_bound(s.begin(), s.end(), t[i].x2) - s.begin(); T.modify(1, l, r - 1, t[i].st); res += T.query(1, 0, s.size() - 2) * (t[i + 1].y - t[i].y); }