jiangly模板-数据结构
数据结构
目录
笛卡尔树
// 2022-11-15 19:30:08
// https://codeforces.com/contest/1748/submission/181116336
std::vector<int> lc(n, -1), rc(n, -1), s;
for (int i = 0; i < n; i++) {
while (!s.empty() && a[i] > a[s.back()]) {
int x = s.back();
rc[x] = lc[i];
lc[i] = x;
s.pop_back();
}
s.push_back(i);
}
while (s.size() > 1) {
int x = s.back();
s.pop_back();
rc[s.back()] = x;
}
树状数组(Fenwick)
/** 树状数组(Fenwick 新版)
* 2023-12-28: https://codeforces.com/contest/1915/submission/239262801
**/
template <typename T>
struct Fenwick {
int n;
std::vector<T> a;
Fenwick(int n_ = 0) {
init(n_);
}
void init(int n_) {
n = n_;
a.assign(n, T{});
}
void add(int x, const T &v) {
for (int i = x + 1; i <= n; i += i & -i) {
a[i - 1] = a[i - 1] + v;
}
}
T sum(int x) {
T ans{};
for (int i = x; i > 0; i -= i & -i) {
ans = ans + a[i - 1];
}
return ans;
}
T rangeSum(int l, int r) {
return sum(r) - sum(l);
}
int select(const T &k) {
int x = 0;
T cur{};
for (int i = 1 << std::__lg(n); i; i /= 2) {
if (x + i <= n && cur + a[x + i - 1] <= k) {
x += i;
cur = cur + a[x - 1];
}
}
return x;
}
};
并查集
并查集(DSU)
/** 可撤销并查集(DSU With Rollback)
* 2024-09-17: https://qoj.ac/submission/569639
**/
/** 并查集(DSU)
* 2023-08-04: https://ac.nowcoder.com/acm/contest/view-submission?submissionId=63239142
**/
struct DSU {
std::vector<int> f, siz;
DSU() {}
DSU(int n) {
init(n);
}
void init(int n) {
f.resize(n);
std::iota(f.begin(), f.end(), 0);
siz.assign(n, 1);
}
int find(int x) {
while (x != f[x]) {
x = f[x] = f[f[x]];
}
return x;
}
bool same(int x, int y) {
return find(x) == find(y);
}
bool merge(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return false;
}
siz[x] += siz[y];
f[y] = x;
return true;
}
int size(int x) {
return siz[find(x)];
}
};
带权并查集
// 2022-08-06 18:08:23
// https://codeforces.com/contest/1713/submission/167259625
struct DSU {
std::vector<int> f, g;
DSU(int n) : f(n), g(n) { std::iota(f.begin(), f.end(), 0); }
std::array<int, 2> leader(int x) {
if (f[x] == x) {
return {x, 0};
}
auto [y, z] = leader(f[x]);
f[x] = y;
g[x] ^= z;
return {f[x], g[x]};
}
bool merge(int a, int b, int z) {
auto [x, u] = leader(a);
auto [y, v] = leader(b);
if (x == y) {
return (u ^ v ^ z) == 0;
}
f[y] = x;
g[y] = u ^ v ^ z;
return true;
}
};
可撤销并查集
// 2026-04-26 22:11:43
// https://codeforces.com/contest/2222/submission/372648762
#include <bits/stdc++.h>
using namespace std;
struct KruskalDSU {
vector<int> p, sz;
int cnt = 0;
long long ans = 0;
KruskalDSU() {}
KruskalDSU(int n) {
init(n);
}
void init(int n) {
p.resize(n + 1);
sz.assign(n + 1, 1);
cnt = n;
ans = 0;
iota(p.begin(), p.end(), 0);
}
int find(int x) {
if (p[x] == x) return x;
return p[x] = find(p[x]);
}
bool unite(int a, int b, int cost) {
int x = find(a);
int y = find(b);
if (x == y) return false;
if (sz[x] < sz[y]) swap(x, y);
p[y] = x;
sz[x] += sz[y];
cnt--;
ans += cost;
return true;
}
};
struct RollbackDSU {
struct Change {
int child;
int parent;
int old_size_parent;
int old_rep_parent;
};
vector<int> p, sz, rep;
vector<Change> stk;
KruskalDSU *mst = nullptr;
RollbackDSU() {}
RollbackDSU(int n, const vector<int> &initial_rep, KruskalDSU *mst_) {
init(n, initial_rep, mst_);
}
void init(int n, const vector<int> &initial_rep, KruskalDSU *mst_) {
p.resize(n + 1);
sz.assign(n + 1, 1);
rep = initial_rep;
mst = mst_;
stk.clear();
stk.reserve(n + 5);
iota(p.begin(), p.end(), 0);
}
int find(int x) {
while (p[x] != x) x = p[x];
return x;
}
int snapshot() const {
return (int)stk.size();
}
void rollback(int snap) {
while ((int)stk.size() > snap) {
Change c = stk.back();
stk.pop_back();
p[c.child] = c.child;
sz[c.parent] = c.old_size_parent;
rep[c.parent] = c.old_rep_parent;
}
}
void unite(int a, int b, int cost) {
int x = find(a);
int y = find(b);
if (x == y) return;
if (sz[x] < sz[y]) swap(x, y);
if (rep[x] != 0 && rep[y] != 0) {
mst->unite(rep[x], rep[y], cost);
}
stk.push_back({y, x, sz[x], rep[x]});
p[y] = x;
sz[x] += sz[y];
if (rep[x] == 0) {
rep[x] = rep[y];
}
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
int n, m, q;
cin >> n >> m >> q;
vector<vector<pair<int, int>>> by_weight(m + 1);
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
by_weight[w].push_back({u, v});
}
KruskalDSU mst(q);
vector<int> rep(n + 1, 0);
vector<int> first_at_color(n + 1, 0);
for (int i = 1; i <= q; i++) {
int c;
cin >> c;
if (first_at_color[c] == 0) {
first_at_color[c] = i;
rep[c] = i;
} else {
mst.unite(first_at_color[c], i, 0);
}
}
RollbackDSU dsu(n, rep, &mst);
auto add_range = [&](int L, int R, int cost) {
if (L > R || mst.cnt == 1) return;
for (int w = L; w <= R; w++) {
for (auto [u, v] : by_weight[w]) {
dsu.unite(u, v, cost);
if (mst.cnt == 1) return;
}
}
};
function<void(int, int)> dfs = [&](int L, int R) {
if (L == R || mst.cnt == 1) return;
int mid = (L + R) >> 1;
int snap = dsu.snapshot();
add_range(mid + 1, R, L);
dfs(L, mid);
dsu.rollback(snap);
snap = dsu.snapshot();
add_range(L, mid, mid + 1);
dfs(mid + 1, R);
dsu.rollback(snap);
};
dfs(0, m);
if (mst.cnt == 1) {
cout << mst.ans << '\n';
} else {
cout << -1 << '\n';
}
}
return 0;
}
/** 可撤销并查集(DSU With Rollback)
* 2024-09-17: https://qoj.ac/submission/569639
**/
struct DSU {
std::vector<int> siz;
std::vector<int> f;
std::vector<std::array<int, 2>> his;
DSU(int n) : siz(n + 1, 1), f(n + 1) {
std::iota(f.begin(), f.end(), 0);
}
int find(int x) {
while (f[x] != x) {
x = f[x];
}
return x;
}
bool merge(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return false;
}
if (siz[x] < siz[y]) {
std::swap(x, y);
}
his.push_back({x, y});
siz[x] += siz[y];
f[y] = x;
return true;
}
int time() {
return his.size();
}
void revert(int tm) {
while (his.size() > tm) {
auto [x, y] = his.back();
his.pop_back();
f[y] = y;
siz[x] -= siz[y];
}
}
};
线段树
线段树(SegmentTree+Info 区间加+单点修改)
/** 线段树(SegmentTree+Info 初始赋值+单点修改+查找前驱后继)
* 2023-07-17: https://ac.nowcoder.com/acm/contest/view-submission?submissionId=62804432
* 2024-06-25: https://codeforces.com/contest/1982/submission/267353839
**/
template<class Info>
struct SegmentTree {
int n;
std::vector<Info> info;
SegmentTree() : n(0) {}
SegmentTree(int n_, Info v_ = Info()) {
init(n_, v_);
}
template<class T>
SegmentTree(std::vector<T> init_) {
init(init_);
}
void init(int n_, Info v_ = Info()) {
init(std::vector(n_, v_));
}
template<class T>
void init(std::vector<T> init_) {
n = init_.size();
info.assign(4 << std::__lg(n), Info());
std::function<void(int, int, int)> build = [&](int p, int l, int r) {
if (r - l == 1) {
info[p] = init_[l];
return;
}
int m = (l + r) / 2;
build(2 * p, l, m);
build(2 * p + 1, m, r);
pull(p);
};
build(1, 0, n);
}
void pull(int p) {
info[p] = info[2 * p] + info[2 * p + 1];
}
void modify(int p, int l, int r, int x, const Info &v) {
if (r - l == 1) {
info[p] = v;
return;
}
int m = (l + r) / 2;
if (x < m) {
modify(2 * p, l, m, x, v);
} else {
modify(2 * p + 1, m, r, x, v);
}
pull(p);
}
void modify(int p, const Info &v) {
modify(1, 0, n, p, v);
}
Info rangeQuery(int p, int l, int r, int x, int y) {
if (l >= y || r <= x) {
return Info();
}
if (l >= x && r <= y) {
return info[p];
}
int m = (l + r) / 2;
return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
}
Info rangeQuery(int l, int r) {
return rangeQuery(1, 0, n, l, r);
}
template<class F>
int findFirst(int p, int l, int r, int x, int y, F &&pred) {
if (l >= y || r <= x) {
return -1;
}
if (l >= x && r <= y && !pred(info[p])) {
return -1;
}
if (r - l == 1) {
return l;
}
int m = (l + r) / 2;
int res = findFirst(2 * p, l, m, x, y, pred);
if (res == -1) {
res = findFirst(2 * p + 1, m, r, x, y, pred);
}
return res;
}
template<class F>
int findFirst(int l, int r, F &&pred) {
return findFirst(1, 0, n, l, r, pred);
}
template<class F>
int findLast(int p, int l, int r, int x, int y, F &&pred) {
if (l >= y || r <= x) {
return -1;
}
if (l >= x && r <= y && !pred(info[p])) {
return -1;
}
if (r - l == 1) {
return l;
}
int m = (l + r) / 2;
int res = findLast(2 * p + 1, m, r, x, y, pred);
if (res == -1) {
res = findLast(2 * p, l, m, x, y, pred);
}
return res;
}
template<class F>
int findLast(int l, int r, F &&pred) {
return findLast(1, 0, n, l, r, pred);
}
};
懒标记线段树(LazySegmentTree)
/** 懒标记线段树(LazySegmentTree)
* 2023-03-03: https://atcoder.jp/contests/joi2023yo2/submissions/39363123
* 2023-03-12: https://codeforces.com/contest/1804/submission/197106837
* 2023-07-17: https://ac.nowcoder.com/acm/contest/view-submission?submissionId=62804432
* 2023-11-12: https://qoj.ac/submission/249505
* 2024-08-14: https://ac.nowcoder.com/acm/contest/view-submission?submissionId=70980889&returnHomeType=1&uid=329687984
**/
template<class Info, class Tag>
struct LazySegmentTree {
int n;
std::vector<Info> info;
std::vector<Tag> tag;
LazySegmentTree() : n(0) {}
LazySegmentTree(int n_, Info v_ = Info()) {
init(n_, v_);
}
template<class T>
LazySegmentTree(std::vector<T> init_) {
init(init_);
}
void init(int n_, Info v_ = Info()) {
init(std::vector(n_, v_));
}
template<class T>
void init(std::vector<T> init_) {
n = init_.size();
info.assign(4 << std::__lg(n), Info());
tag.assign(4 << std::__lg(n), Tag());
std::function<void(int, int, int)> build = [&](int p, int l, int r) {
if (r - l == 1) {
info[p] = init_[l];
return;
}
int m = (l + r) / 2;
build(2 * p, l, m);
build(2 * p + 1, m, r);
pull(p);
};
build(1, 0, n);
}
void pull(int p) {
info[p] = info[2 * p] + info[2 * p + 1];
}
void apply(int p, const Tag &v) {
info[p].apply(v);
tag[p].apply(v);
}
void push(int p) {
apply(2 * p, tag[p]);
apply(2 * p + 1, tag[p]);
tag[p] = Tag();
}
void modify(int p, int l, int r, int x, const Info &v) {
if (r - l == 1) {
info[p] = v;
return;
}
int m = (l + r) / 2;
push(p);
if (x < m) {
modify(2 * p, l, m, x, v);
} else {
modify(2 * p + 1, m, r, x, v);
}
pull(p);
}
void modify(int p, const Info &v) {
modify(1, 0, n, p, v);
}
Info rangeQuery(int p, int l, int r, int x, int y) {
if (l >= y || r <= x) {
return Info();
}
if (l >= x && r <= y) {
return info[p];
}
int m = (l + r) / 2;
push(p);
return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
}
Info rangeQuery(int l, int r) {
return rangeQuery(1, 0, n, l, r);
}
void rangeApply(int p, int l, int r, int x, int y, const Tag &v) {
if (l >= y || r <= x) {
return;
}
if (l >= x && r <= y) {
apply(p, v);
return;
}
int m = (l + r) / 2;
push(p);
rangeApply(2 * p, l, m, x, y, v);
rangeApply(2 * p + 1, m, r, x, y, v);
pull(p);
}
void rangeApply(int l, int r, const Tag &v) {
return rangeApply(1, 0, n, l, r, v);
}
void half(int p, int l, int r) {
if (info[p].act == 0) {
return;
}
if ((info[p].min + 1) / 2 == (info[p].max + 1) / 2) {
apply(p, {-(info[p].min + 1) / 2});
return;
}
int m = (l + r) / 2;
push(p);
half(2 * p, l, m);
half(2 * p + 1, m, r);
pull(p);
}
void half() {
half(1, 0, n);
}
template<class F>
int findFirst(int p, int l, int r, int x, int y, F &&pred) {
if (l >= y || r <= x) {
return -1;
}
if (l >= x && r <= y && !pred(info[p])) {
return -1;
}
if (r - l == 1) {
return l;
}
int m = (l + r) / 2;
push(p);
int res = findFirst(2 * p, l, m, x, y, pred);
if (res == -1) {
res = findFirst(2 * p + 1, m, r, x, y, pred);
}
return res;
}
template<class F>
int findFirst(int l, int r, F &&pred) {
return findFirst(1, 0, n, l, r, pred);
}
template<class F>
int findLast(int p, int l, int r, int x, int y, F &&pred) {
if (l >= y || r <= x) {
return -1;
}
if (l >= x && r <= y && !pred(info[p])) {
return -1;
}
if (r - l == 1) {
return l;
}
int m = (l + r) / 2;
push(p);
int res = findLast(2 * p + 1, m, r, x, y, pred);
if (res == -1) {
res = findLast(2 * p, l, m, x, y, pred);
}
return res;
}
template<class F>
int findLast(int l, int r, F &&pred) {
return findLast(1, 0, n, l, r, pred);
}
void maintainL(int p, int l, int r, int pre) {
if (info[p].difl > 0 && info[p].maxlowl < pre) {
return;
}
if (r - l == 1) {
info[p].max = info[p].maxlowl;
info[p].maxl = info[p].maxr = l;
info[p].maxlowl = info[p].maxlowr = -inf;
return;
}
int m = (l + r) / 2;
push(p);
maintainL(2 * p, l, m, pre);
pre = std::max(pre, info[2 * p].max);
maintainL(2 * p + 1, m, r, pre);
pull(p);
}
void maintainL() {
maintainL(1, 0, n, -1);
}
void maintainR(int p, int l, int r, int suf) {
if (info[p].difr > 0 && info[p].maxlowr < suf) {
return;
}
if (r - l == 1) {
info[p].max = info[p].maxlowl;
info[p].maxl = info[p].maxr = l;
info[p].maxlowl = info[p].maxlowr = -inf;
return;
}
int m = (l + r) / 2;
push(p);
maintainR(2 * p + 1, m, r, suf);
suf = std::max(suf, info[2 * p + 1].max);
maintainR(2 * p, l, m, suf);
pull(p);
}
void maintainR() {
maintainR(1, 0, n, -1);
}
};
struct Tag {
int x = 0;
void apply(const Tag &t) & {
x = std::max(x, t.x);
}
};
struct Info {
int x = 0;
void apply(const Tag &t) & {
x = std::max(x, t.x);
}
};
Info operator+(const Info &a, const Info &b) {
return {std::max(a.x, b.x)};
}
珂朵莉树ODT
// https://codeforces.com/contest/1638/submission/146415172
// 2022-02-14 19:01:15
#include <bits/stdc++.h>
using i64 = long long;
template <typename T>
struct Fenwick {
const int n;
std::vector<T> a;
Fenwick(int n) : n(n), a(n) {}
void add(int x, T v) {
for (int i = x + 1; i <= n; i += i & -i) {
a[i - 1] += v;
}
}
T sum(int x) {
T ans = 0;
for (int i = x; i > 0; i -= i & -i) {
ans += a[i - 1];
}
return ans;
}
T rangeSum(int l, int r) {
return sum(r) - sum(l);
}
};
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, q;
std::cin >> n >> q;
std::vector<i64> add(n);
std::map<int, int> s;
s[0] = 0;
s[n] = -1;
auto split = [&](int x) {
auto it = std::prev(s.upper_bound(x));
s[x] = it->second;
};
Fenwick<i64> fen(n);
auto rangeAdd = [&](int l, int r, i64 x) {
fen.add(l, x);
fen.add(r, -x);
};
for (int i = 0; i < q; i++) {
std::string op;
std::cin >> op;
if (op == "Color") {
int l, r, c;
std::cin >> l >> r >> c;
l--;
c--;
split(l);
split(r);
auto it = s.find(l);
while (it->first != r) {
rangeAdd(it->first, std::next(it)->first, add[it->second] - add[c]);
it = s.erase(it);
}
s[l] = c;
} else if (op == "Add") {
int c, x;
std::cin >> c >> x;
c--;
add[c] += x;
} else {
int j;
std::cin >> j;
j--;
split(j);
std::cout << fen.sum(j + 1) + add[s[j]] << "\n";
}
}
return 0;
}
状压RMQ
/** 状压RMQ(RMQ)
* 2023-03-02: https://atcoder.jp/contests/joi2022ho/submissions/39351739
* 2023-09-04: https://qoj.ac/submission/163598
* 2024-08-07: https://atcoder.jp/contests/abc365/submissions/56438692
**/
template<class T,
class Cmp = std::less<T>>
struct RMQ {
const Cmp cmp = Cmp();
static constexpr unsigned B = 64;
using u64 = unsigned long long;
int n;
std::vector<std::vector<T>> a;
std::vector<T> pre, suf, ini;
std::vector<u64> stk;
RMQ() {}
RMQ(const std::vector<T> &v) {
init(v);
}
void init(const std::vector<T> &v) {
n = v.size();
pre = suf = ini = v;
stk.resize(n);
if (!n) {
return;
}
const int M = (n - 1) / B + 1;
const int lg = std::__lg(M);
a.assign(lg + 1, std::vector<T>(M));
for (int i = 0; i < M; i++) {
a[0][i] = v[i * B];
for (int j = 1; j < B && i * B + j < n; j++) {
a[0][i] = std::min(a[0][i], v[i * B + j], cmp);
}
}
for (int i = 1; i < n; i++) {
if (i % B) {
pre[i] = std::min(pre[i], pre[i - 1], cmp);
}
}
for (int i = n - 2; i >= 0; i--) {
if (i % B != B - 1) {
suf[i] = std::min(suf[i], suf[i + 1], cmp);
}
}
for (int j = 0; j < lg; j++) {
for (int i = 0; i + (2 << j) <= M; i++) {
a[j + 1][i] = std::min(a[j][i], a[j][i + (1 << j)], cmp);
}
}
for (int i = 0; i < M; i++) {
const int l = i * B;
const int r = std::min(1U * n, l + B);
u64 s = 0;
for (int j = l; j < r; j++) {
while (s && cmp(v[j], v[std::__lg(s) + l])) {
s ^= 1ULL << std::__lg(s);
}
s |= 1ULL << (j - l);
stk[j] = s;
}
}
}
T operator()(int l, int r) {
if (l / B != (r - 1) / B) {
T ans = std::min(suf[l], pre[r - 1], cmp);
l = l / B + 1;
r = r / B;
if (l < r) {
int k = std::__lg(r - l);
ans = std::min({ans, a[k][l], a[k][r - (1 << k)]}, cmp);
}
return ans;
} else {
int x = B * (l / B);
return ini[__builtin_ctzll(stk[r - 1] >> (l - x)) + l];
}
}
};
取莫类
Treap
// https://codeforces.com/contest/38/submission/200537139
// https://ac.nowcoder.com/acm/contest/view-submission?submissionId=63162242
#include <bits/stdc++.h>
using i64 = long long;
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
struct Info {
int imp = 0;
int id = 0;
};
Info operator+(Info a, Info b) {
return {std::max(a.imp, b.imp), 0};
}
struct Node {
int w = rng();
Info info;
Info sum;
int siz = 1;
Node *l = nullptr;
Node *r = nullptr;
};
void pull(Node *t) {
t->sum = t->info;
t->siz = 1;
if (t->l) {
t->sum = t->l->sum + t->sum;
t->siz += t->l->siz;
}
if (t->r) {
t->sum = t->sum + t->r->sum;
t->siz += t->r->siz;
}
}
std::pair<Node *, Node *> splitAt(Node *t, int p) {
if (!t) {
return {t, t};
}
if (p <= (t->l ? t->l->siz : 0)) {
auto [l, r] = splitAt(t->l, p);
t->l = r;
pull(t);
return {l, t};
} else {
auto [l, r] = splitAt(t->r, p - 1 - (t->l ? t->l->siz : 0));
t->r = l;
pull(t);
return {t, r};
}
}
void insertAt(Node *&t, int p, Node *x) {
if (!t) {
t = x;
return;
}
if (x->w < t->w) {
auto [l, r] = splitAt(t, p);
t = x;
t->l = l;
t->r = r;
pull(t);
return;
}
if (p <= (t->l ? t->l->siz : 0)) {
insertAt(t->l, p, x);
} else {
insertAt(t->r, p - 1 - (t->l ? t->l->siz : 0), x);
}
pull(t);
}
Node *merge(Node *a, Node *b) {
if (!a) {
return b;
}
if (!b) {
return a;
}
if (a->w < b->w) {
a->r = merge(a->r, b);
pull(a);
return a;
} else {
b->l = merge(a, b->l);
pull(b);
return b;
}
}
int query(Node *t, int v) {
if (!t) {
return 0;
}
if (t->sum.imp < v) {
return t->siz;
}
int res = query(t->r, v);
if (res != (t->r ? t->r->siz : 0)) {
return res;
}
if (t->info.imp > v) {
return res;
}
return res + 1 + query(t->l, v);
}
void dfs(Node *t) {
if (!t) {
return;
}
dfs(t->l);
std::cout << t->info.id << " ";
dfs(t->r);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
Node *t = nullptr;
for (int i = 0; i < n; i++) {
int a, c;
std::cin >> a >> c;
int p = i - std::min(c, query(t, a));
auto x = new Node;
x->info = {a, i + 1};
x->sum = {a, 0};
insertAt(t, p, x);
}
dfs(t);
std::cout << "\n";
return 0;
}
Slpay
LCT
// https://cf.dianhsu.com/gym/104479/submission/221036520
struct Node {
Node *ch[2], *p;
bool rev;
int siz = 1;
Node() : ch{nullptr, nullptr}, p(nullptr), rev(false) {}
};
void reverse(Node *t) {
if (t) {
std::swap(t->ch[0], t->ch[1]);
t->rev ^= 1;
}
}
void push(Node *t) {
if (t->rev) {
reverse(t->ch[0]);
reverse(t->ch[1]);
t->rev = false;
}
}
void pull(Node *t) {
t->siz = (t->ch[0] ? t->ch[0]->siz : 0) + 1 + (t->ch[1] ? t->ch[1]->siz : 0);
}
bool isroot(Node *t) {
return t->p == nullptr || (t->p->ch[0] != t && t->p->ch[1] != t);
}
int pos(Node *t) {
return t->p->ch[1] == t;
}
void pushAll(Node *t) {
if (!isroot(t)) {
pushAll(t->p);
}
push(t);
}
void rotate(Node *t) {
Node *q = t->p;
int x = !pos(t);
q->ch[!x] = t->ch[x];
if (t->ch[x]) {
t->ch[x]->p = q;
}
t->p = q->p;
if (!isroot(q)) {
q->p->ch[pos(q)] = t;
}
t->ch[x] = q;
q->p = t;
pull(q);
}
void splay(Node *t) {
pushAll(t);
while (!isroot(t)) {
if (!isroot(t->p)) {
if (pos(t) == pos(t->p)) {
rotate(t->p);
} else {
rotate(t);
}
}
rotate(t);
}
pull(t);
}
void access(Node *t) {
for (Node *i = t, *q = nullptr; i; q = i, i = i->p) {
splay(i);
i->ch[1] = q;
pull(i);
}
splay(t);
}
void makeroot(Node *t) {
access(t);
reverse(t);
}
void link(Node *x, Node *y) {
makeroot(x);
x->p = y;
}
void split(Node *x, Node *y) {
makeroot(x);
access(y);
}
void cut(Node *x, Node *y) {
split(x, y);
x->p = y->ch[0] = nullptr;
pull(y);
}
int dist(Node *x, Node *y) {
split(x, y);
return y->siz - 1;
}
分数四则运算(Frac)
/** 分数四则运算(Frac)
* 2024-07-30: https://qoj.ac/submission/498911
**/
template<class T>
struct Frac {
T num;
T den;
Frac(T num_, T den_) : num(num_), den(den_) {
if (den < 0) {
den = -den;
num = -num;
}
}
Frac() : Frac(0, 1) {}
Frac(T num_) : Frac(num_, 1) {}
explicit operator double() const {
return 1. * num / den;
}
Frac &operator+=(const Frac &rhs) {
num = num * rhs.den + rhs.num * den;
den *= rhs.den;
return *this;
}
Frac &operator-=(const Frac &rhs) {
num = num * rhs.den - rhs.num * den;
den *= rhs.den;
return *this;
}
Frac &operator*=(const Frac &rhs) {
num *= rhs.num;
den *= rhs.den;
return *this;
}
Frac &operator/=(const Frac &rhs) {
num *= rhs.den;
den *= rhs.num;
if (den < 0) {
num = -num;
den = -den;
}
return *this;
}
friend Frac operator+(Frac lhs, const Frac &rhs) {
return lhs += rhs;
}
friend Frac operator-(Frac lhs, const Frac &rhs) {
return lhs -= rhs;
}
friend Frac operator*(Frac lhs, const Frac &rhs) {
return lhs *= rhs;
}
friend Frac operator/(Frac lhs, const Frac &rhs) {
return lhs /= rhs;
}
friend Frac operator-(const Frac &a) {
return Frac(-a.num, a.den);
}
friend bool operator==(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den == rhs.num * lhs.den;
}
friend bool operator!=(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den != rhs.num * lhs.den;
}
friend bool operator<(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den < rhs.num * lhs.den;
}
friend bool operator>(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den > rhs.num * lhs.den;
}
friend bool operator<=(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den <= rhs.num * lhs.den;
}
friend bool operator>=(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den >= rhs.num * lhs.den;
}
friend std::ostream &operator<<(std::ostream &os, Frac x) {
T g = std::gcd(x.num, x.den);
if (x.den == g) {
return os << x.num / g;
} else {
return os << x.num / g << "/" << x.den / g;
}
}
};
线性基(Basis)
/** 线性基(Basis)
* 2023-12-03: https://codeforces.com/contest/1902/submission/235594491
**/
struct Basis {
int a[20] {};
int t[20] {};
Basis() {
std::fill(t, t + 20, -1);
}
void add(int x, int y = 1E9) {
for (int i = 0; i < 20; i++) {
if (x >> i & 1) {
if (y > t[i]) {
std::swap(a[i], x);
std::swap(t[i], y);
}
x ^= a[i];
}
}
}
bool query(int x, int y = 0) {
for (int i = 0; i < 20; i++) {
if ((x >> i & 1) && t[i] >= y) {
x ^= a[i];
}
}
return x == 0;
}
};
高精度(BigInt)
/** 高精度(BigInt)
* 2023-09-11: https://qoj.ac/submission/176420
**/
constexpr int N = 1000;
struct BigInt {
int a[N];
BigInt(int x = 0) : a{} {
for (int i = 0; x; i++) {
a[i] = x % 10;
x /= 10;
}
}
BigInt &operator*=(int x) {
for (int i = 0; i < N; i++) {
a[i] *= x;
}
for (int i = 0; i < N - 1; i++) {
a[i + 1] += a[i] / 10;
a[i] %= 10;
}
return *this;
}
BigInt &operator/=(int x) {
for (int i = N - 1; i >= 0; i--) {
if (i) {
a[i - 1] += a[i] % x * 10;
}
a[i] /= x;
}
return *this;
}
BigInt &operator+=(const BigInt &x) {
for (int i = 0; i < N; i++) {
a[i] += x.a[i];
if (a[i] >= 10) {
a[i + 1] += 1;
a[i] -= 10;
}
}
return *this;
}
};
std::ostream &operator<<(std::ostream &o, const BigInt &a) {
int t = N - 1;
while (a.a[t] == 0) {
t--;
}
for (int i = t; i >= 0; i--) {
o << a.a[i];
}
return o;
}

浙公网安备 33010602011771号