枚举子集
for (int x = s; x; x = (x - 1) & s) {}
高维前缀和
for (int i = 0; i < m; ++i) for (int j = 0; j < (1 << m); ++j) if (j & (1 << i)) f[j] += f[j ^ (1 << i)]; for (int i = 0; i < m; ++i) for (int j = 0; j < (1 << m); ++j) if (!(j & (1 << i))) f[j] += f[j | (1 << i)];
线性基
void insert(long long x) { for (int i = 62; ~i; --i) if (x >> i) { if (!p[i]) { p[i] = x; break; } x ^= p[i]; } } void rebuild() { for (int i = 62; ~i; --i) for (int j = i - 1; ~j; --j) if (p[i] & (1LL << j)) p[i] ^= p[j]; }
线性求逆元
inv[1] = 1; for (int i = 2; i <= n; ++i) inv[i] = 1LL * (p - p / i) * inv[p % i] % p;
欧拉筛
void sieve() { np[1] = 1, phi[1] = mu[1] = 1; for (int i = 2; i <= n; ++i) { if (!np[i]) p[++tot] = i, phi[i] = i - 1, mu[i] = -1; for (int j = 1; j <= tot && i * p[j] <= n; ++j) { np[i * p[j]] = 1; if (i % p[j] == 0) { phi[i * p[j]] = phi[i] * p[j], mu[i * p[j]] = 0; break; } phi[i * p[j]] = phi[i] * (p[j] - 1), mu[i * p[j]] = -mu[i]; } } }
文艺平衡树
#include <cstdio> #include <algorithm> const int N = 100002; int a[N], val[N], rev[N], siz[N], fa[N], ch[N][2], rt, cnt, n, m; int read() { int x = 0; char c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); return x; } int get(int x) { return ch[fa[x]][1] == x; } void maintain(int x) { siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1; } void tab(int x) { rev[x] ^= 1, std::swap(ch[x][0], ch[x][1]); } void pushdown(int x) { if (ch[x][0]) tab(ch[x][0]); if (ch[x][1]) tab(ch[x][1]); rev[x] = 0; } void build(int &cur, int pre, int l, int r) { if (l > r) return; cur = ++cnt; int mid = (l + r) >> 1; val[cur] = a[mid], fa[cur] = pre; build(ch[cur][0], cur, l, mid - 1); build(ch[cur][1], cur, mid + 1, r); maintain(cur); } void rotate(int x) { int y = fa[x], z = fa[y], k = get(x); if (rev[y]) pushdown(y); if (rev[x]) pushdown(x); if (z) ch[z][get(y)] = x; ch[y][k] = ch[x][k ^ 1], ch[x][k ^ 1] = y; fa[ch[y][k]] = y, fa[y] = x, fa[x] = z; maintain(y), maintain(x); } void splay(int x, int z) { for (int y; (y = fa[x]) != z; rotate(x)) if (fa[y] != z) rotate(get(x) ^ get(y) ? x : y); if (!z) rt = x; } int find(int k) { int x = rt; for (;;) { if (rev[x]) pushdown(x); if (siz[ch[x][0]] + 1 == k) return x; if (siz[ch[x][0]] >= k) x = ch[x][0]; else k -= siz[ch[x][0]] + 1, x = ch[x][1]; } } void print(int x) { if (rev[x]) pushdown(x); if (ch[x][0]) print(ch[x][0]); if (1 <= val[x] && val[x] <= n) printf("%d ", val[x]); if (ch[x][1]) print(ch[x][1]); } int main() { n = read(), m = read(); for (int i = 2; i <= n + 1; ++i) a[i] = i - 1; a[1] = 0, a[n + 2] = n + 1, build(rt, 0, 1, n + 2); while (m--) { int l = read(), r = read(); l = find(l), r = find(r + 2), splay(l, 0), splay(r, l), tab(ch[r][0]); } print(rt); return 0; }
主席树
#include <cstdio> #include <algorithm> const int N = 200002, M = 3800002; int a[N], b[N], sum[M], ls[M], rs[M], rt[N], cnt; int read() { int x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); return x * f; } int find(int x, int l, int r) { while (l <= r) { int mid = (l + r) >> 1; if (b[mid] == x) return mid; if (b[mid] < x) l = mid + 1; else r = mid - 1; } } void insert(int &x, int y, int l, int r, int p) { x = ++cnt, sum[x] = sum[y] + 1; if (l == r) return; int mid = (l + r) >> 1; if (p <= mid) rs[x] = rs[y], insert(ls[x], ls[y], l, mid, p); if (mid < p) ls[x] = ls[y], insert(rs[x], rs[y], mid + 1, r, p); } int query(int x, int y, int l, int r, int k) { if (l == r) return b[l]; int mid = (l + r) >> 1; if (sum[ls[x]] - sum[ls[y]] >= k) return query(ls[x], ls[y], l, mid, k); return query(rs[x], rs[y], mid + 1, r, k - sum[ls[x]] + sum[ls[y]]); } int main() { int n = read(), m = read(); for (int i = 1; i <= n; ++i) a[i] = b[i] = read(); std::sort(b + 1, b + n + 1); for (int i = 1; i <= n; ++i) insert(rt[i], rt[i - 1], 1, n, find(a[i], 1, n)); while (m--) { int l = read(), r = read(), k = read(); printf("%d\n", query(rt[r], rt[l - 1], 1, n, k)); } return 0; }
二维线段树
#include <cstdio> #include <algorithm> int ans, n, m, q; int read() { int x = 0; char c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); return x; } struct Node { int mx[2050], tag[2050]; void update(int cur, int l, int r, int L, int R, int x) { mx[cur] = std::max(mx[cur], x); if (L <= l && r <= R) { tag[cur] = std::max(tag[cur], x); return; } int mid = (l + r) >> 1; if (L <= mid) update(cur << 1, l, mid, L, R, x); if (mid < R) update(cur << 1 | 1, mid + 1, r, L, R, x); } int query(int cur, int l, int r, int L, int R) { if (L <= l && r <= R) return mx[cur]; int mid = (l + r) >> 1, res = tag[cur]; if (L <= mid) res = std::max(res, query(cur << 1, l, mid, L, R)); if (mid < R) res = std::max(res, query(cur << 1 | 1, mid + 1, r, L, R)); return res; } } mx[2050], tag[2050]; void update(int cur, int l, int r, int L, int R, int yl, int yr, int x) { mx[cur].update(1, 1, m, yl, yr, x); if (L <= l && r <= R) { tag[cur].update(1, 1, m, yl, yr, x); return; } int mid = (l + r) >> 1; if (L <= mid) update(cur << 1, l, mid, L, R, yl, yr, x); if (mid < R) update(cur << 1 | 1, mid + 1, r, L, R, yl, yr, x); } int query(int cur, int l, int r, int L, int R, int yl ,int yr) { if (L <= l && r <= R) return mx[cur].query(1, 1, m, yl, yr); int mid = (l + r) >> 1, res = tag[cur].query(1, 1, m, yl, yr); if (L <= mid) res = std::max(res, query(cur << 1, l, mid, L, R, yl, yr)); if (mid < R) res = std::max(res, query(cur << 1 | 1, mid + 1, r, L, R, yl, yr)); return res; } int main() { n = read() + 1, m = read() + 1, q = read(); while (q--) { int d = read(), s = read(), h = read(), x = read() + 1, y = read() + 1; int tmp = query(1, 1, n, x, x + d - 1, y, y + s - 1) + h; update(1, 1, n, x, x + d - 1, y, y + s - 1, tmp), ans = std::max(ans, tmp); } printf("%d\n", ans); return 0; }