[笔记]各种模板
启动。
快排(带随机)
void qsort(int l, int r) {
if (l >= r) return;
vector<int> p, q; p.clear(), q.clear();
for (int i = l; i <= r; i ++ ) {
if (a[i] < a[l]) p.push_back(a[i]);
if (a[i] > a[l]) q.push_back(a[i]);
}
int u = l, v = r, val = a[l];
for (int i : p) a[u ++ ] = i;
for (int i : q) a[v -- ] = i;
for (int i = u; i <= v; i ++ ) a[i] = val;
qsort(l, u - 1); qsort(v + 1, r);
}
int main() {
random_shuffle(a + 1, a + n + 1);
qsort(1, n);
}
归并排序
void merge(int l, int r) {
if (l >= r) return;
int mid = l + r >> 1;
merge(l, mid), merge(mid + 1, r);
int i = l, j = mid + 1; vector<int> tmp;
while (i <= mid and j <= r)
tmp.push_back((a[i] < a[j] ? a[i ++ ] : a[j ++ ]));
while (i <= mid) tmp.push_back(a[i ++ ]);
while (j <= r) tmp.push_back(a[j ++ ]);
for (int i : tmp) a[l ++ ] = i;
}
单调队列(滑窗)
int n, k, a[N], q[N], hh, tt;
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i ++ )
scanf("%d", &a[i]);
hh = 1, tt = 0;
for (int i = 1; i <= n; i ++ ) {
while (hh <= tt and q[hh] <= i - k) hh ++ ;
while (hh <= tt and a[q[tt]] >= a[i]) tt -- ;
q[ ++ tt] = i; if (i >= k) printf("%d ", a[q[hh]]);
} hh = 1, tt = 0; puts("");
for (int i = 1; i <= n; i ++ ) {
while (hh <= tt and q[hh] <= i - k) hh ++ ;
while (hh <= tt and a[q[tt]] <= a[i]) tt -- ;
q[ ++ tt] = i; if (i >= k) printf("%d ", a[q[hh]]);
} return 0;
}
三分
const double eps = 1e-6;
int n; double l, r, a[20];
double f(double x) {
double fac = 1.00, ans = 0.00;
for (int i = 0; i <= n; i ++ )
ans += a[i] * fac, fac *= x;
return ans;
}
double search(double l, double r) {
if (fabs(r - l) <= eps) return l;
double mid1 = l + (r - l) / 3.0;
double mid2 = r - (r - l) / 3.0;
if (f(mid1) > f(mid2)) return search(l, mid2);
else return search(mid1, r);
}
int main() {
scanf("%d%lf%lf", &n, &l, &r);
for (int i = n; ~i; i -- )
scanf("%lf", &a[i]);
printf("%.10lf\n", search(l, r));
}
矩阵快速幂
int Mod(int a, int b) {
return (a % mod + b % mod + mod) % mod;
}
struct Matrix {
#define MAX 100
#define all(i) for (int i = (0); i < MAX; i ++ )
int a[MAX][MAX];
Matrix() { memset(a, 0, sizeof a); }
void makeI() { all(i) a[i][i] = 1; }
int *operator [] (const int &x) { return a[x]; }
Matrix operator + (Matrix &b)const {
Matrix ans; all(i) all(j)
ans[i][j] = Mod(a[i][j], b[i][j]); return ans;
}
Matrix operator - (Matrix &b)const {
Matrix ans; all(i) all(j)
ans[i][j] = Mod(a[i][j], -b[i][j]); return ans;
}
Matrix operator * (Matrix &b)const {
Matrix ans; all(i) all(j) all(k)
ans[i][j] = Mod(ans[i][j], a[i][k] * b[k][j] % mod); return ans;
}
Matrix operator ^ (int b)const {
Matrix ans, tmp = *this; ans.makeI();
for (; b; b >>= 1, tmp = tmp * tmp)
if (b & 1) ans = ans * tmp; return ans;
}
}M;
signed main() {
scanf("%lld%lld", &n, &k);
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
scanf("%lld", &M[i][j]);
M = M ^ k;
}
树状数组 1
int n, m, tr[N];
int main() {
auto add = [&](int x, int v) {
for (int i = x; i <= n; i += lowbit(i))
tr[i] += v;
};
auto query = [&](int x) -> int {
int ans = 0;
for (int i = x; i; i -= lowbit(i))
ans += tr[i]; return ans;
};
scanf("%d%d", &n, &m);
for (int i = 1, x; i <= n; i ++ )
scanf("%d", &x), add(i, x);
while (m -- ) {
int op, a, b; scanf("%d%d%d", &op, &a, &b);
if (op & 1) add(a, b);
else printf("%d\n", query(b) - query(a - 1));
} return 0;
}
树状数组 2
int n, m, tr[N], w[N];
signed main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ )
scanf("%d", &w[i]);
auto add = [&](int x, int v) {
for (int i = x; i <= n; i += lowbit(i))
tr[i] += v;
};
auto query = [&](int x) -> int {
int ans = 0;
for (int i = x; i; i -= lowbit(i))
ans += tr[i]; return ans;
};
while (m -- ) {
int op, x, y, k; scanf("%d", &op);
if (op & 1) scanf("%d%d%d", &x, &y, &k),
add(x, k), add(y + 1, -k);
else scanf("%d", &x),
printf("%d\n", w[x] + query(x));
}
}
树状数组 3(区间加区间查询)
int n, m, tr1[N], tr2[N], a[N];
signed main() {
auto add = [&](int *tr, int x, int v) {
for (int i = x; i <= n; i += lowbit(i))
tr[i] += v;
};
auto query = [&](int *tr, int x) {
int ans = 0;
for (int i = x; i; i -= lowbit(i))
ans += tr[i]; return ans;
};
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= n; i ++ ) {
scanf("%lld", &a[i]);
add(tr1, i, a[i] - a[i - 1]);
add(tr2, i, (i - 1) * (a[i] - a[i - 1]));
}
while (m -- ) {
int op, l, r, v;
scanf("%lld%lld%lld", &op, &l, &r);
if (op & 1) {
scanf("%lld", &v);
add(tr1, l, v);
add(tr1, r + 1, -v);x
add(tr2, l, (l - 1) * v);
add(tr2, r + 1, - r * v);
} else {
l -- ;
printf("%lld\n", query(tr1, r) * r - query(tr2, r) -
query(tr1, l) * l + query(tr2, l));
}
} return 0;
}
乘法逆元 1
int fac[N], inv[N], n, p;
int qpow(int a, int b = p - 2) {
int ans = 1; for (; b; b >>= 1, a = 1ll * a * a % p)
if (b & 1) ans = 1ll * ans * a % p; return ans;
}
int main() {
scanf("%d%d", &n, &p); fac[0] = 1;
for (int i = 1; i <= n; i ++ )
fac[i] = 1ll * fac[i - 1] * i % p;
inv[n] = qpow(fac[n]);
for (int i = n - 1; i >= 1; i -- )
inv[i] = 1ll * inv[i + 1] * (i + 1) % p;
for (int i = 1; i <= n; i ++ )
inv[i] = 1ll * inv[i] * fac[i - 1] % p;
for (int i = 1; i <= n; i ++ )
printf("%d\n", inv[i]);
}
乘法逆元 2
int n, p, k, ans, a[N], fac[N], inv[N];
int qpow(int a, int b = p - 2) {
int ans = 1; for (; b; b >>= 1, a = 1ll * a * a % p)
if (b & 1) ans = 1ll * ans * a % p; return ans;
}
int main() {
read(n, p, k); fac[0] = 1;
for (int i = 1; i <= n; i ++ ) {
read(a[i]);
fac[i] = 1ll * fac[i - 1] * a[i] % p;
}
inv[n] = qpow(fac[n]);
for (int i = n - 1; i; i -- )
inv[i] = 1ll * inv[i + 1] * a[i + 1] % p;
for (int i = 1; i <= n; i ++ ) {
inv[i] = 1ll * inv[i] * fac[i - 1] % p;
ans = (ans + 1ll * (fac[0] = 1ll * fac[0] * k % p) * inv[i] % p) % p;
}
}
dijkstra
priority_queue<PII, vector<PII>, greater<PII>> q;
fill(dist, dist + n + 1, (1ll << 31) - 1);
dist[s] = 0; q.push({0, s});
while (q.size()) {
int u = q.top().second; q.pop();
if (st[u]) continue; st[u] = true;
for (int i = h[u]; i; i = ne[i]) {
int v = e[i];
if (dist[v] > dist[u] + w[i]) {
dist[v] = dist[u] + w[i];
if (!st[v]) q.push({dist[v], v});
}
}
}
for (int i = 1; i <= n; i ++ )
printf("%d ", dist[i]);
SPFA
fill(dist, dist + n + 1, (1ll << 31) - 1);
queue<int> q; q.push(s); dist[s] = 0; st[s] = true;
while (q.size()) {
int u = q.front(); q.pop();
st[u] = false; for (int i = h[u]; i; i = ne[i]) {
int v = e[i]; if (dist[v] > dist[u] + w[i]) {
dist[v] = dist[u] + w[i];
if (!st[v]) st[v] = true, q.push(v);
}
}
}
KMP
scanf("%s%s", s1 + 1, s2 + 1);
n = strlen(s1 + 1), m = strlen(s2 + 1);
for (int i = 2, j = 0; i <= m; i ++ ) {
while (j and s2[i] != s2[j + 1]) j = ne[j];
ne[i] = (s2[i] == s2[j + 1]) ? ( ++ j) : j;
}
for (int i = 1, j = 0; i <= n; i ++ ) {
while (j and s2[j + 1] != s1[i]) j = ne[j];
if ((s2[j + 1] == s1[i] ? ++ j : j) == m)
printf("%d\n", i - m + 1);
}
ST 表
for (int i = 2; i <= n; i ++ )
lg[i] = lg[i >> 1] + 1;
for (int i = 1; i <= n; i ++ )
scanf("%d", &st[i][0]);
for (int j = 1; j <= lg[n]; j ++ )
for (int i = 1; i + (1 << j - 1) <= n; i ++ )
st[i][j] = max(st[i][j - 1], st[i + (1 << j - 1)][j - 1]);
while (m -- ) {
int l, r; scanf("%d%d", &l, &r);
int d = lg[r - l + 1];
printf("%d\n", max(st[l][d], st[r - (1 << d) + 1][d]));
}
Bezout 定理
int gcd(int a, int b) {
return !b ? a : gcd(b, a % b);
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i ++ )
scanf("%d", &a[i]);
for (int i = 1; i <= n; i ++ )
d = gcd(a[i] < 0 ? - a[i] : a[i], d);
printf("%d\n", d); return 0;
}
单调栈
for (int i = n; i; i -- ) {
while (top and a[stk[top]] <= a[i]) top -- ;
ne[i] = stk[top]; stk[ ++ top] = i;
}
康托展开
auto add = [&](int x, int v) {
for (int i = x; i <= n; i += lowbit(i))
tr[i] += v;
};
auto query = [&](int x) {
int s = 0; for (int i = x; i; i -= lowbit(i))
s += tr[i]; return s;
};
for (int i = 1; i <= n; i ++ )
add(i, 1); fac[0] = 1ll;
for (int i = 1; i <= n; i ++ )
fac[i] = 1ll * fac[i - 1] * i % mod;
for (int i = 1; i <= n; i ++ ) {
int qwq = query(a[i] - 1); add(a[i], -1);
ans = 1ll * (ans + 1ll * qwq * fac[n - i]) % mod;
} printf("%d\n", (ans + 1) % mod);
最长公共子序列
我比较傻,不会二分,只会线段树优化
void build(int u, int l, int r) {
tr[u] = {l, r};
if (l == r) return;
build(ls, l, mid), build(rs, mid + 1, r);
}
void modify(int u, int x, int v) {
tr[u].mx = max(tr[u].mx, v);
if (tr[u].l == tr[u].r) return;
if (x <= mid) modify(ls, x, v);
else modify(rs, x, v);
}
int query(int u, int l, int r) {
if (tr[u].l >= l and tr[u].r <= r)
return tr[u].mx;
int s = 0; if (l <= mid) s = query(ls, l, r);
if (r > mid) s = max(s, query(rs, l, r)); return s;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i ++ )
scanf("%d", &s[i]);
for (int i = 1; i <= n; i ++ )
scanf("%d", &t[i]);
for (int i = 1; i <= n; i ++ )
id[s[i]] = i;
for (int i = 1; i <= n; i ++ )
t[i] = id[t[i]];
build(1, 1, n);
for (int i = 1; i <= n; i ++ ) {
f[i] = query(1, 1, t[i]) + 1;
modify(1, t[i], f[i]);
}
int ans = 0;
for (int i = 1; i <= n; i ++ )
ans = max(ans, f[i]);
printf("%d\n", ans);
return 0;
}
拉格朗日插值
int n, k, ans, x[N], y[N];
int Mod(int x, int y) {
return (x + y + mod) % mod;
}
int qpow(int a, int b = mod - 2) {
int ans = 1; for (; b; b >>= 1, a = a * a % mod)
if (b & 1) ans = ans * a % mod; return ans;
}
signed main() {
scanf("%lld%lld", &n, &k);
for (int i = 1; i <= n; i ++ )
scanf("%lld%lld", &x[i], &y[i]);
for (int i = 1; i <= n; i ++ ) {
int now = 1; for (int j = 1; j <= n; j ++ ) {
if (j != i) now = now * Mod(k, -x[j]) % mod * qpow(Mod(x[i], -x[j])) % mod;
} ans = Mod(ans, y[i] * now);
} printf("%lld\n", ans); return 0;
}
笛卡尔树
for (int i = 1; i <= n; i ++ ) {
while (top and w[stk[top]] > w[i]) top -- ;
if (!top) ls[i] = stk[top + 1];
else ls[i] = rs[stk[top]], rs[stk[top]] = i;
stk[ ++ top] = i;
}
有理数取余
void read(int &x) {
x = 0; char ch = getchar();
for (; ch < '0' or ch > '9'; ch = getchar());
for (; ch >= '0' and ch <= '9'; ch = getchar())
x = ((x << 1) + (x << 3) + (ch ^ 48)) % mod;
}
int qpow(int a, int b = mod - 2) {
int ans = 1;
for (; b; b >>= 1, a = a * a % mod)
if (b & 1) ans = ans * a % mod; return ans;
}
signed main() {
read(a), read(b);
printf("%lld\n", a * qpow(b) % mod);
}