代码模板
目录
DS
// 372647698
// 372648762 (KruskalDSU rollback)
// 372649357 (HLD ord版)
// 375447272 (treap )
// 375466130 (rebuilt segtree)
// 375832338 (advance lazysegtree)
// 378264476(fastscan seg BITMin)
// 378266021 (coverTree oneTree)
// 367936311 enum
// 367727170 kmp
// 367086731 Matrix power
// https://codeforces.com/contest/1902/submission/235594491 Basic Xor
随机数
// https://codeforces.com/contest/2219/submission/371036839
中心扩展
// 2022-06-27 11:35:45
// https://codeforces.com/contest/1519/submission/161927828
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> a(n), b(n);
i64 sum = 0;
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
for (int i = 0; i < n; i++) {
std::cin >> b[i];
sum += 1LL * a[i] * b[i];
}
i64 ans = sum;
for (int s = 0; s <= 2 * n - 2; s++) {
i64 cur = sum;
for (int i = s / 2; i >= 0 && s - i < n; i--) {
cur -= 1LL * a[i] * b[i] + 1LL * a[s - i] * b[s - i];
cur += 1LL * a[i] * b[s - i] + 1LL * a[s - i] * b[i];
ans = std::max(ans, cur);
}
}
std::cout << ans << "\n";
return 0;
}
/*
for (int i = 0; i < 2 * n - 1; ++i) {
int l = i / 2, r = (i + 1) / 2;
i64 sum = s;
for (; l >= 0 && r < n; --l, ++r) {
sum += 1LL * (a[r] - a[l]) * (b[l] - b[r]);
ans = std::max(ans, sum);
}
}
*/
线段树合并
// 2026-04-09 19:31:06
// https://codeforces.com/contest/700/submission/370450479
// http://codeforces.com/contest/2219/submission/371006515
#include <bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using u128 = unsigned __int128;
using i128 = __int128;
namespace rgs = std::ranges;
struct SAM {
static constexpr int ALPHABET_SIZE = 26;
struct Node {
int len;
int link;
std::array<int, ALPHABET_SIZE> next;
Node() : len{}, link{}, next{} {}
};
std::vector<Node> t;
SAM() {
init();
}
void init() {
t.assign(2, Node());
t[0].next.fill(1);
t[0].len = -1;
}
int newNode() {
t.emplace_back();
return t.size() - 1;
}
int extend(int p, int c) {
if (t[p].next[c]) {
int q = t[p].next[c];
if (t[q].len == t[p].len + 1) {
return q;
}
int r = newNode();
t[r].len = t[p].len + 1;
t[r].link = t[q].link;
t[r].next = t[q].next;
t[q].link = r;
while (t[p].next[c] == q) {
t[p].next[c] = r;
p = t[p].link;
}
return r;
}
int cur = newNode();
t[cur].len = t[p].len + 1;
while (!t[p].next[c]) {
t[p].next[c] = cur;
p = t[p].link;
}
t[cur].link = extend(p, c);
return cur;
}
int extend(int p, char c, char offset = 'a') {
return extend(p, c - offset);
}
int next(int p, int x) {
return t[p].next[x];
}
int next(int p, char c, char offset = 'a') {
return next(p, c - offset);
}
int link(int p) {
return t[p].link;
}
int len(int p) {
return t[p].len;
}
int size() {
return t.size();
}
};
constexpr int N = 200000 * 2 * 20;
struct Node {
int l;
int r;
int sum;
};
std::vector<Node> t(N);
int tot = 0;
int add(int l, int r, int x) {
int o = ++tot;
t[o].sum = 1;
if (r - l == 1) {
return o;
}
int m = (l + r) / 2;
if (x < m) {
t[o].l = add(l, m, x);
} else {
t[o].r = add(m, r, x);
}
return o;
}
int merge(int p, int q) {
if (!p) {
return q;
}
if (!q) {
return p;
}
int o = ++tot;
t[o].sum = t[p].sum + t[q].sum;
t[o].l = merge(t[p].l, t[q].l);
t[o].r = merge(t[p].r, t[q].r);
return o;
}
int query(int o, int l, int r, int x, int y) {
if (!o || l >= y || r <= x) {
return 0;
}
if (l >= x && r <= y) {
return t[o].sum;
}
int m = (l + r) / 2;
return query(t[o].l, l, m, x, y) + query(t[o].r, m, r, x, y);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::string s;
std::cin >> s;
SAM sam;
int p = 1;
std::vector<int> ends(n + 1);
ends[0] = 1;
for (int i = 1; i <= n; i++) {
p = sam.extend(p, s[i - 1]);
ends[i] = p;
}
std::vector<std::vector<int>> adj(sam.size());
std::vector<int> any(sam.size());
for (int i = 2; i < sam.size(); i++) {
adj[sam.link(i)].push_back(i);
}
std::vector<int> rt(sam.size());
for (int i = 0; i <= n; i++) {
rt[ends[i]] = add(0, n + 1, i);
any[ends[i]] = i;
}
[&](this auto &&self, int x) -> void {
for (auto y : adj[x]) {
self(y);
rt[x] = merge(rt[x], rt[y]);
}
} (1);
std::vector<int> dp(sam.size());
std::vector<int> g(sam.size());
[&](this auto &&self, int x) -> void {
for (auto y : adj[x]) {
int l = any[y] - sam.len(y) + sam.len(g[x]);
int r = any[y];
if (query(rt[x], 0, n + 1, l, r)) {
dp[y] = dp[x] + 1;
g[y] = y;
} else {
dp[y] = dp[x];
g[y] = g[x];
}
self(y);
}
} (1);
int ans = rgs::max(dp);
std::cout << ans << "\n";
return 0;
}
平衡树
fhq-treap
#include <bits/stdc++.h>
constexpr int L = 4E6 + 5;
constexpr int MINV = -1E7 - 5;
constexpr int MAXV = 1E7 + 5;
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
struct Node {
int l, r;
int siz = 0;
int cnt = 0;
int w;
int x;
} node[L];
void push(int t) {}
void pull(int t) {
node[t].siz = node[node[t].l].siz + node[node[t].r].siz + node[t].cnt;
}
std::pair<int, int> split(int t, int x) {
if (!t) {
return {t, t};
}
push(t);
if (x < node[t].x) {
auto [l, r] = split(node[t].l, x);
node[t].l = r;
pull(t);
return {l, t};
} else {
auto [l, r] = split(node[t].r, x);
node[t].r = l;
pull(t);
return {t, r};
}
}
int merge(int l, int r) {
if (!l || !r) {
return l ? l : r;
}
if (node[l].w < node[r].w) {
node[l].r = merge(node[l].r, r);
pull(l);
return l;
} else {
node[r].l = merge(l, node[r].l);
pull(r);
return r;
}
}
int newNode(int x) {
static int tot = 0;
++tot;
node[tot].x = x;
node[tot].w = rng();
return tot;
}
void insert(int &t, int x) {
auto [l, u] = split(t, x - 1);
auto [v, r] = split(u, x);
if (!v) {
v = newNode(x);
}
if (x == node[v].x) {
++node[v].cnt;
pull(v);
}
t = merge(l, merge(v, r));
}
void erase(int &t, int x) {
auto [l, u] = split(t, x - 1);
auto [v, r] = split(u, x);
if (node[v].cnt > 1) {
--node[v].cnt;
pull(v);
} else {
v = 0;
}
t = merge(l, merge(v, r));
}
int rank(int t, int x) {
int res = 0;
while (t) {
if (node[t].x < x) {
res += node[node[t].l].siz + node[t].cnt;
t = node[t].r;
} else {
t = node[t].l;
}
}
return res;
}
int get(int t, int x) {
while (t) {
int l = node[node[t].l].siz;
if (l <= x && x < l + node[t].cnt) {
return node[t].x;
}
if (x < l) {
t = node[t].l;
} else {
x -= l + node[t].cnt;
t = node[t].r;
}
}
return 0;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
int t = 0;
while (n--) {
int op, x;
std::cin >> op >> x;
if (op == 1) {
insert(t, x);
} else if (op == 2) {
erase(t, x);
} else if (op == 3) {
std::cout << rank(t, x) + 1 << "\n";
} else if (op == 4) {
std::cout << get(t, x - 1) << "\n";
} else if (op == 5) {
int k = rank(t, x);
std::cout << get(t, k - 1) << "\n";
} else {
int k = rank(t, x + 1);
std::cout << get(t, k) << "\n";
}
}
}
pb_ds
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
template <class T>
using ordered_set = __gnu_pbds::tree<
std::pair<T, int>,
__gnu_pbds::null_type,
std::less<>,
__gnu_pbds::rb_tree_tag,
// __gnu_pbds::splay_tree_tag,
__gnu_pbds::tree_order_statistics_node_update
>;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
int idx = 0;
ordered_set<int> t;
while (n--) {
int op, x;
std::cin >> op >> x;
if (op == 1) {
t.insert({x, idx++});
} else if (op == 2) {
auto it = t.lower_bound({x, -1});
if (it != t.end() && it->first == x) {
t.erase(it);
}
} else if (op == 3) {
std::cout << t.order_of_key({x, -1}) + 1 << "\n";
} else if (op == 4) {
std::cout << t.find_by_order(x - 1)->first << "\n";
} else if (op == 5) {
// int k = t.order_of_key({x, -1}) - 1;
// auto it = t.find_by_order(k);
auto it = std::prev(t.lower_bound({x, -1}));
std::cout << it->first << "\n";
} else {
// int k = t.order_of_key({x + 1, -1});
// auto it = t.find_by_order(k);
auto it = t.lower_bound({x + 1, -1});
std::cout << it->first << "\n";
}
}
}
动态开点线段树
#include <bits/stdc++.h>
constexpr int L = 4E6 + 5;
constexpr int MINV = -1E7 - 5;
constexpr int MAXV = 1E7 + 5;
struct Node {
int l, r;
int cnt = 0;
int x;
} node[L];
int newNode(int t = 0) {
static int tot = 0;
++tot;
node[tot] = node[t];
return tot;
}
void add(int &p, int l, int r, int x, int t = 1) {
if (!p) {
p = newNode(p);
}
node[p].cnt += t;
if (r - l == 1) {
return;
}
int m = (r + l) / 2;
if (x < m) {
add(node[p].l, l, m, x, t);
} else {
add(node[p].r, m, r, x, t);
}
}
void insert(int &t, int x) {
return add(t, MINV, MAXV, x);
}
void erase(int &t, int x) {
return add(t, MINV, MAXV, x, -1);
}
int rank(int t, int l, int r, int x) {
if (!t || r - l == 1) {
return 0;
}
int m = (r + l) / 2;
if (x < m) {
return rank(node[t].l, l, m, x);
}
return node[node[t].l].cnt + rank(node[t].r, m, r, x);
}
int rank(int t, int x) {
return rank(t, MINV, MAXV, x);
}
int get(int p, int l, int r, int x) {
if (r - l == 1) {
return l;
}
int m = (r + l) / 2;
int t = node[node[p].l].cnt;
if (x < t) {
return get(node[p].l, l, m, x);
}
return get(node[p].r, m, r, x - t);
}
int get(int t, int x) {
return get(t, MINV, MAXV, x);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
int t = 0;
while (n--) {
int op, x;
std::cin >> op >> x;
if (op == 1) {
insert(t, x);
} else if (op == 2) {
erase(t, x);
} else if (op == 3) {
std::cout << rank(t, x) + 1 << "\n";
} else if (op == 4) {
std::cout << get(t, x - 1) << "\n";
} else if (op == 5) {
int k = rank(t, x);
std::cout << get(t, k - 1) << "\n";
} else {
int k = rank(t, x + 1);
std::cout << get(t, k) << "\n";
}
}
}
splay
#include <bits/stdc++.h>
constexpr int N = 100000 + 5;
constexpr int INF = std::numeric_limits<int>::max();
struct Node {
int ch[2], p;
int v, cnt, siz;
} nodes[N];
int root, tot;
int newNode(int x) {
int u = ++tot;
nodes[u].v = x;
// nodes[u].cnt = nodes[u].siz = 1;
return u;
}
void pull(int u) {
nodes[u].siz = nodes[nodes[u].ch[0]].siz + nodes[nodes[u].ch[1]].siz + nodes[u].cnt;
}
int pos(int u) {
return nodes[nodes[u].p].ch[1] == u;
}
void rotate(int u) {
int p = nodes[u].p, g = nodes[p].p;
int k = pos(u);
nodes[g].ch[nodes[g].ch[1] == p] = u;
nodes[u].p = g;
nodes[p].ch[k] = nodes[u].ch[k ^ 1];
nodes[nodes[u].ch[k ^ 1]].p = p;
nodes[u].ch[k ^ 1] = p;
nodes[p].p = u;
pull(p);
pull(u);
}
void splay(int u) {
while (nodes[u].p) {
int p = nodes[u].p;
if (nodes[p].p) {
rotate(pos(u) == pos(p) ? p : u);
}
rotate(u);
}
root = u;
}
void insert(int &t, int x, int p = 0) {
if (!t) {
t = newNode(x);
nodes[t].p = p;
}
if (nodes[t].v == x) {
++nodes[t].cnt;
pull(t);
splay(t);
return;
}
if (x < nodes[t].v) {
insert(nodes[t].ch[0], x, t);
} else {
insert(nodes[t].ch[1], x, t);
}
}
int nth(int k) {
int u = root;
while (u) {
int l = nodes[nodes[u].ch[0]].siz;
if (k < l) {
u = nodes[u].ch[0];
} else if (k < l + nodes[u].cnt) {
splay(u);
return nodes[u].v;
} else {
k -= l + nodes[u].cnt;
u = nodes[u].ch[1];
}
}
return 0;
}
int rank(int x) {
int u = root;
int res = 0;
int lst = u;
while (u) {
lst = u;
if (nodes[u].v < x) {
res += nodes[nodes[u].ch[0]].siz + nodes[u].cnt;
u = nodes[u].ch[1];
} else {
u = nodes[u].ch[0];
}
}
splay(lst);
return res;
}
void del(int t, int x) {
if (nodes[t].v != x) {
return del(nodes[t].ch[nodes[t].v < x], x);
}
splay(t);
if (nodes[t].cnt > 1) {
--nodes[t].cnt;
pull(t);
return;
}
int l = nodes[t].ch[0], r = nodes[t].ch[1];
if (!l || !r) {
root = l | r;
nodes[root].p = 0;
return;
}
nodes[l].p = nodes[r].p = 0;
root = l;
int p = l;
while (nodes[p].ch[1]) {
p = nodes[p].ch[1];
}
splay(p);
nodes[root].ch[1] = r;
nodes[r].p = root;
pull(root);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
while (n--) {
int op, x;
std::cin >> op >> x;
if (op == 1) {
insert(root, x);
} else if (op == 2) {
del(root, x);
} else if (op == 3) {
std::cout << rank(x) + 1 << '\n';
} else if (op == 4) {
std::cout << nth(x - 1) << "\n";
} else if (op == 5) {
int k = rank(x);
std::cout << nth(k - 1) << "\n";
} else {
int k = rank(x + 1);
std::cout << nth(k) << "\n";
}
}
}
字符串哈希
#include <bits/stdc++.h>
using i64 = long long;
struct Hash {
static constexpr int N = 2;
static constexpr std::array<i64, N> P{1000000007LL, 1000000009LL};
static constexpr i64 B = 13331;
std::array<i64, N> x{};
constexpr Hash() = default;
constexpr Hash(i64 v) {
for (int j = 0; j < N; ++j) {
x[j] = (v % P[j] + P[j]) % P[j];
}
}
constexpr Hash &operator+=(const Hash &h) & {
for (int j = 0; j < N; ++j) {
x[j] = (x[j] + h.x[j]) % P[j];
}
return *this;
}
constexpr Hash &operator-=(const Hash &h) & {
for (int j = 0; j < N; ++j) {
x[j] = (x[j] - h.x[j] + P[j]) % P[j];
}
return *this;
}
constexpr Hash &operator*=(const Hash &h) & {
for (int j = 0; j < N; ++j) {
x[j] = x[j] * h.x[j] % P[j];
}
return *this;
}
friend constexpr Hash operator+(Hash a, const Hash &b) {
return a += b;
}
friend constexpr Hash operator-(Hash a, const Hash &b) {
return a -= b;
}
friend constexpr Hash operator*(Hash a, const Hash &b) {
return a *= b;
}
// friend constexpr bool operator==(const Hash &a, const Hash &b) {
// return a.x == b.x;
// }
// friend constexpr bool operator<(const Hash &a, const Hash &b) {
// return a.x < b.x;
// }
// friend constexpr std::strong_ordering operator<=>(const Hash &a, const Hash &b) {
// return a.x <=> b.x;
// }
friend constexpr bool operator==(const Hash &a, const Hash &b) = default;
friend constexpr auto operator<=>(const Hash &a, const Hash &b) = default;
};
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int m, q;
std::cin >> m >> q;
std::string t;
std::cin >> t;
std::vector<Hash> p(m + 1);
std::vector<Hash> h(m + 1);
p[0] = 1;
for (int i = 0; i < m; ++i) {
p[i + 1] = p[i] * Hash::B;
}
for (int i = 0; i < m; ++i) {
h[i + 1] = h[i] * Hash::B + t[i];
}
auto get = [&](int l, int r) -> Hash { return h[r] - h[l] * p[r - l]; };
while (q--) {
int l1, r1, l2, r2;
std::cin >> l1 >> r1 >> l2 >> r2;
--l1, --l2;
std::cout << (get(l1, r1) == get(l2, r2) ? "Yes" : "No") << "\n";
}
}
快排
sort
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> a(n);
for (auto &x : a) {
std::cin >> x;
}
auto partition = [&](int l, int r, int x) -> std::pair<int, int> {
int i = l;
while (i < r) {
if (a[i] > x) {
std::swap(a[i], a[--r]);
} else if (a[i] < x) {
std::swap(a[i++], a[l++]);
} else {
++i;
}
}
return {l, r};
};
auto sort = [&](auto &&self, int l, int r) -> void {
if (r - l <= 1) {
return;
}
int x = a[(l + r) / 2];
auto [L, R] = partition(l, r, x);
self(self, l, L);
self(self, R, r);
};
sort(sort, 0, n);
for (auto x : a) {
std::cout << x << " ";
}
}
nth
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, k;
std::cin >> n >> k;
--k;
std::vector<int> a(n);
for (auto &x : a) {
std::cin >> x;
}
auto partition = [&](int l, int r, int x) -> std::pair<int, int> {
int i = l;
while (i < r) {
if (a[i] > x) {
std::swap(a[i], a[--r]);
} else if (a[i] < x) {
std::swap(a[i++], a[l++]);
} else {
++i;
}
}
return {l, r};
};
auto nth = [&](int l, int r, int k) -> void {
while (r - l > 1) {
int x = a[(l + r) / 2];
auto [L, R] = partition(l, r, x);
if (k < L) {
r = L;
} else if (R <= k) {
l = R;
} else {
break;
}
}
};
nth(0, n, k);
std::cout << a[k];
}
树套树
#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 1E8 + 5;
constexpr int L = 6E7 + 5;
struct Node {
int l = 0, r = 0;
int cnt = 0;
} node[L];
int tot = 0;
int newNode() {
return ++tot;
}
void add(int &p, int l, int r, int x, int v) {
if (!p) {
p = newNode();
}
node[p].cnt += v;
if (r - l == 1) {
return;
}
int m = (l + r) / 2;
if (x < m) {
add(node[p].l, l, m, x, v);
} else {
add(node[p].r, m, r, x, v);
}
}
int query(std::vector<int> &&t1, std::vector<int> &&t2, int l, int r, int k) {
if (r - l == 1) {
return 0;
}
int m = (l + r) / 2;
if (k < m) {
for (auto &t : t1) {
t = node[t].l;
}
for (auto &t : t2) {
t = node[t].l;
}
return query(std::move(t1), std::move(t2), l, m, k);
} else {
int s = 0;
for (auto &t : t1) {
s -= node[node[t].l].cnt;
t = node[t].r;
}
for (auto &t : t2) {
s += node[node[t].l].cnt;
t = node[t].r;
}
return s + query(std::move(t1), std::move(t2), m, r, k);
}
}
int qry(std::vector<int> &&t1, std::vector<int> &&t2, int l, int r, int k) {
if (r - l == 1) {
return l;
}
int m = (l + r) / 2;
int s = 0;
for (auto &t : t1) {
s -= node[node[t].l].cnt;
}
for (auto &t : t2) {
s += node[node[t].l].cnt;
}
if (k <= s) {
for (auto &t : t1) {
t = node[t].l;
}
for (auto &t : t2) {
t = node[t].l;
}
return qry(std::move(t1), std::move(t2), l, m, k);
} else {
for (auto &t : t1) {
t = node[t].r;
}
for (auto &t : t2) {
t = node[t].r;
}
return qry(std::move(t1), std::move(t2), m, r, k - s);
}
}
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, int v, int t = 1) {
for (int i = x + 1; i <= n; i += i & -i) {
::add(a[i - 1], 0, N, v, t);
}
}
std::vector<int> sum(int x) {
std::vector<int> ans;
for (int i = x; i > 0; i -= i & -i) {
ans.push_back(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, m;
std::cin >> n >> m;
std::vector<int> a(n);
Fenwick<int> fen(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
fen.add(i, a[i]);
}
auto getRank = [&](int l, int r, int k) {
return query(fen.sum(l), fen.sum(r), 0, N, k);
};
auto getVal = [&](int l, int r, int k) {
return qry(fen.sum(l), fen.sum(r), 0, N, k);
};
while (m--) {
int opt;
std::cin >> opt;
if (opt == 1) {
int l, r, k;
std::cin >> l >> r >> k;
--l;
std::cout << getRank(l, r, k) + 1 << "\n";
} else if (opt == 2){
int l, r, k;
std::cin >> l >> r >> k;
--l;
std::cout << getVal(l, r, k) << "\n";
} else if (opt == 3) {
int p, k;
std::cin >> p >> k;
--p;
fen.add(p, a[p], -1);
a[p] = k;
fen.add(p, a[p]);
} else if (opt == 4){
int l, r, k;
std::cin >> l >> r >> k;
--l;
int t = getRank(l, r, k);
if (t == 0) {
std::cout << -2147483647 << "\n";
} else {
std::cout << getVal(l, r, t) << "\n";
}
} else {
int l, r, k;
std::cin >> l >> r >> k;
--l;
int t = getRank(l, r, k + 1);
if (t == r - l) {
std::cout << 2147483647 << "\n";
} else {
std::cout << getVal(l, r, t + 1) << "\n";
}
}
}
}
LCA
#include <bits/stdc++.h>
using i64 = long long;
template<typename T>
struct RangeMinimumQuery {
std::vector<std::vector<T>> st;
std::function<bool(T, T)> cmp;
RangeMinimumQuery() {}
RangeMinimumQuery(const std::vector<T> &a, const std::function<bool(T, T)> &cmp = std::less<T>()) {
init(a, cmp);
}
void init(const std::vector<T> &a, const std::function<bool(T, T)> &_cmp = std::less<T>()) {
cmp = _cmp;
int n = a.size();
int l = std::__lg(n);
st.assign(n, std::vector<T>(l + 1));
for (int i = 0; i < n; ++i)
st[i][0] = a[i];
for (int j = 1; j <= l; ++j)
for (int i = 0; i + (1 << j) <= n; ++i)
st[i][j] = std::min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1], cmp);
}
T rangeMin(int l, int r) {
int k = std::__lg(r - l);
return std::min(st[l][k], st[r - (1 << k)][k], cmp);
}
};
template<class T,
class Cmp = std::less<T>>
struct RMQ {
// const Cmp cmp = Cmp();
std::function<bool(T, T)> 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, auto cmp) {
this->cmp = cmp;
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];
}
}
};
struct LowestCommonAncestor {
std::vector<int> dep, euler;
// RangeMinimumQuery<int> rmq;
std::function<bool(int, int)> cmp = [&](int a, int b) -> bool {
return dep[a] < dep[b];
};
RMQ<int> rmq;
std::vector<int> seq;
LowestCommonAncestor() {}
LowestCommonAncestor(const std::vector<std::vector<int>> &e, int s) {
init(e, s);
}
void init(const std::vector<std::vector<int>> &e, int s) {
int n = e.size();
euler.resize(n);
dep.resize(n);
int clock = 0;
std::function<void(int, int)> dfs = [&](int u, int p) {
euler[u] = clock++;
seq.push_back(u);
for (auto v : e[u]) {
if (v == p)
continue;
dep[v] = dep[u] + 1;
dfs(v, u);
seq.push_back(u);
++clock;
}
};
dfs(s, -1);
rmq.init(seq, cmp);
}
int lca(int u, int v) {
if (euler[u] > euler[v])
std::swap(u, v);
return rmq(euler[u], euler[v] + 1);
// return rmq.rangeMin(euler[u], euler[v] + 1);
}
int dist(int u, int v) {
return dep[u] + dep[v] - 2 * dep[lca(u, v)];
}
} t;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m, s;
std::cin >> n >> m >> s;
--s;
std::vector<std::vector<int>> adj(n);
for (int i = 1, u, v; i < n; ++i) {
std::cin >> u >> v;
--u, --v;
adj[u].push_back(v);
adj[v].push_back(u);
}
t.init(adj, s);
for (int i = 0; i < m; ++i) {
int u, v;
std::cin >> u >> v;
--u, --v;
std::cout << t.lca(u, v) + 1 << "\n";
}
}
FHQ-Treap
#include <bits/stdc++.h>
using i64 = long long;
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
constexpr int L = 1E5 + 5;
struct Node {
int w = rng();
int x = -1;
int siz = 0;
int tag = 0;
int l = 0, r = 0;
} node[L];
int tot = 0;
int newNode(int x) {
node[++tot].x = x;
node[tot].siz = 1;
return tot;
}
void pull(int t) {
node[t].siz = node[node[t].l].siz + node[node[t].r].siz + 1;
}
void tag(int t) {
if (t) {
node[t].tag ^= 1;
}
}
void push(int t) {
if (node[t].tag) {
std::swap(node[t].l, node[t].r);
tag(node[t].l);
tag(node[t].r);
node[t].tag = 0;
}
}
std::pair<int, int> splitAt(int t, int p) {
if (!t) {
return {t, t};
}
push(t);
if (p <= node[node[t].l].siz) {
auto [l, r] = splitAt(node[t].l, p);
node[t].l = r;
pull(t);
return {l, t};
} else {
auto [l, r] = splitAt(node[t].r, p - node[node[t].l].siz - 1);
node[t].r = l;
pull(t);
return {t, r};
}
}
int merge(int l, int r) {
if (!l || !r) {
return !l ? r : l;
}
if (node[l].w < node[r].w) {
push(l);
node[l].r = merge(node[l].r, r);
pull(l);
return l;
} else {
push(r);
node[r].l = merge(l, node[r].l);
pull(r);
return r;
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
int t = 0;
for (int i = 1; i <= n; ++i) {
t = merge(t, newNode(i));
}
auto dfs = [&](auto &&self, int u) -> void {
if (u == 0) {
return;
}
push(u);
self(self, node[u].l);
std::cout << node[u].x << " ";
self(self, node[u].r);
};
for (int i = 0; i < m; ++i) {
int l, r;
std::cin >> l >> r;
auto [u, v] = splitAt(t, r);
auto [p, q] = splitAt(u, l - 1);
tag(q);
t = merge(merge(p, q), v);
}
dfs(dfs, t);
}
可持久化 Trie
带着HLD 是因为懒,不想写lca
#include <bits/stdc++.h>
using i64 = long long;
constexpr int L = 6500005;
struct Node {
int ch[2] {};
int cnt = 0;
} pool[L];
int tot = 0;
int newNode(int t = 0) {
pool[++tot] = pool[t];
return tot;
}
int insert(int t, int x) {
int root = newNode(t);
int p = root;
++pool[p].cnt;
for (int i = 30; i >= 0; --i) {
int b = x >> i & 1;
pool[p].ch[b] = newNode(pool[p].ch[b]);
p = pool[p].ch[b];
++pool[p].cnt;
}
return root;
}
int query(int t1, int t2, int x) {
int res = 0;
for (int i = 30; i >= 0; --i) {
int u = ~x >> i & 1;
int cnt = pool[pool[t1].ch[u]].cnt - pool[pool[t2].ch[u]].cnt;
if (cnt > 0) {
res |= 1 << i;
} else {
u = !u;
}
t1 = pool[t1].ch[u];
t2 = pool[t2].ch[u];
}
return res;
}
int query(int a, int b, int c, int d, int x) {
int res = 0;
for (int i = 30; i >= 0; --i) {
int u = ~x >> i & 1;
int cnt = pool[pool[a].ch[u]].cnt + pool[pool[b].ch[u]].cnt
- pool[pool[c].ch[u]].cnt - pool[pool[d].ch[u]].cnt;
if (cnt > 0) {
res |= 1 << i;
} else {
u = !u;
}
a = pool[a].ch[u];
b = pool[b].ch[u];
c = pool[c].ch[u];
d = pool[d].ch[u];
}
return res;
}
struct HLD {
int n;
std::vector<int> siz, top, dep, parent, in, out, seq;
std::vector<std::vector<int>> adj;
int cur;
HLD() {}
HLD(int n) {
init(n);
}
void init(int n) {
this->n = n;
siz.resize(n);
top.resize(n);
dep.resize(n);
parent.resize(n);
in.resize(n);
out.resize(n);
seq.resize(n);
cur = 0;
adj.assign(n, {});
}
void addEdge(int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
void work(int root = 0) {
top[root] = root;
dep[root] = 0;
parent[root] = -1;
dfs1(root);
dfs2(root);
}
void dfs1(int u) {
if (parent[u] != -1) {
adj[u].erase(std::find(adj[u].begin(), adj[u].end(), parent[u]));
}
siz[u] = 1;
for (auto &v : adj[u]) {
parent[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
siz[u] += siz[v];
if (siz[v] > siz[adj[u][0]]) {
std::swap(v, adj[u][0]);
}
}
}
void dfs2(int u) {
in[u] = cur++;
seq[in[u]] = u;
for (auto v : adj[u]) {
top[v] = v == adj[u][0] ? top[u] : v;
dfs2(v);
}
out[u] = cur;
}
int lca(int u, int v) {
while (top[u] != top[v]) {
if (dep[top[u]] > dep[top[v]]) {
u = parent[top[u]];
} else {
v = parent[top[v]];
}
}
return dep[u] < dep[v] ? u : v;
}
int dist(int u, int v) {
return dep[u] + dep[v] - 2 * dep[lca(u, v)];
}
int jump(int u, int k) {
if (dep[u] < k) {
return -1;
}
int d = dep[u] - k;
while (dep[top[u]] > d) {
u = parent[top[u]];
}
return seq[in[u] - dep[u] + d];
}
bool isAncester(int u, int v) {
return in[u] <= in[v] && in[v] < out[u];
}
int rootedParent(int u, int v) {
std::swap(u, v);
if (u == v) {
return u;
}
if (!isAncester(u, v)) {
return parent[u];
}
auto it = std::upper_bound(adj[u].begin(), adj[u].end(), v, [&](int x, int y) {
return in[x] < in[y];
}) - 1;
return *it;
}
int rootedSize(int u, int v) {
if (u == v) {
return n;
}
if (!isAncester(v, u)) {
return siz[v];
}
return n - siz[rootedParent(u, v)];
}
int rootedLca(int a, int b, int c) {
return lca(a, b) ^ lca(b, c) ^ lca(c, a);
}
};
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
std::vector<int> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
HLD t(n);
for (int i = 0, u, v; i < n - 1; ++i) {
std::cin >> u >> v;
--u, --v;
t.addEdge(u, v);
}
t.work();
auto &adj = t.adj;
std::vector<int> pathRoot(n), pre(n + 1);
auto dfs = [&](auto &&self, int u) -> void {
for (auto v : adj[u]) {
pathRoot[v] = insert(pathRoot[u], a[v]);
self(self, v);
}
};
pathRoot[0] = insert(0, a[0]);
dfs(dfs, 0);
for (int i = 0; i < n; ++i) {
pre[i + 1] = insert(pre[i], a[t.seq[i]]);
}
while (m--) {
int op;
std::cin >> op;
if (op == 1) {
int x, z;
std::cin >> x >> z;
--x;
std::cout << query(pre[t.out[x]], pre[t.in[x]], z) << "\n";
} else {
int x, y, z;
std::cin >> x >> y >> z;
--x, --y;
int l = t.lca(x, y);
int p = t.parent[l] == -1 ? 0 : pathRoot[t.parent[l]];
std::cout << std::max(query(pathRoot[x], p, z), query(pathRoot[y], p, z)) << "\n";
// std::cout << query(pathRoot[x], pathRoot[y], pathRoot[l], p, z) << "\n";
}
}
}
可持久化线段树
ADD
#include <bits/stdc++.h>
using i64 = long long;
constexpr int L = 1E5 + 5;
struct Node {
int l = 0, r = 0;
char c;
} node[20 * L];
int tot = 0;
int newNode(int t = 0) {
node[++tot] = node[t];
return tot;
}
int add(int t, int l, int r, int x, char v) {
t = newNode(t);
if (r - l == 1) {
node[t].c = v;
return t;
}
int m = (l + r) / 2;
if (x < m) {
node[t].l = add(node[t].l, l, m, x, v);
} else {
node[t].r = add(node[t].r, m, r, x, v);
}
return t;
}
char query(int t, int l, int r, int x) {
if (r - l == 1) {
return node[t].c;
}
int m = (l + r) / 2;
if (x < m) {
return query(node[t].l, l, m, x);
}
return query(node[t].r, m, r, x);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> roots(1);
std::vector<int> cnt(1);
for (int i = 0; i < n; ++i) {
char op;
std::cin >> op;
if (op == 'T') {
char x;
std::cin >> x;
int t = add(roots.back(), 0, n, cnt.back(), x);
roots.push_back(t);
cnt.push_back(cnt.back() + 1);
} else if (op == 'U') {
int x;
std::cin >> x;
roots.push_back(roots[roots.size() - x - 1]);
cnt.push_back(cnt[cnt.size() - x - 1]);
} else {
int x;
std::cin >> x;
--x;
std::cout << query(roots.back(), 0, n, x) << "\n";
}
}
}
其一
#include <bits/stdc++.h>
using i64 = long long;
constexpr int L = 2E7 + 4;
struct Node {
Node *ch[2] {};
i64 s = 0;
} pool[L];
int tot = 0;
Node *newNode(Node *t) {
if (t) {
pool[tot] = *t;
}
return &pool[tot++];
}
Node *add(Node *t, int l, int r, int x) {
t = newNode(t);
t->s += x;
if (r - l == 1) {
return t;
}
int m = (r + l) / 2;
if (x < m) {
t->ch[0] = add(t->ch[0], l, m, x);
} else {
t->ch[1] = add(t->ch[1], m, r, x);
}
return t;
}
int query(Node *t1, Node *t2, int l, int r, int x, int y) {
if (y <= l || r <= x) {
return 0;
}
if (x <= l && r <= y) {
return (t2 ? t2->s : 0) - (t1 ? t1->s : 0);
}
int m = (l + r) / 2;
return query(t1 ? t1->ch[0] : nullptr, t2 ? t2->ch[0] : nullptr, l, m, x, y) + query(t1 ? t1->ch[1] : nullptr, t2 ? t2->ch[1] : nullptr, m, r, x, y);
}
constexpr int N = 1E9 + 4;
bool chmax(auto &x, int y) {
if (x >= y) {
return false;
}
x = y;
return true;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> a(n);
std::vector<Node *> rt(n + 1);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
rt[i + 1] = add(rt[i], 0, N, a[i]);
}
int m;
std::cin >> m;
auto get = [&](int l, int r) -> int {
int ans = 1;
while (chmax(ans, query(rt[l], rt[r], 0, N, 0, ans + 1) + 1))
;
return ans;
};
for (int i = 0; i < m; ++i) {
int l, r;
std::cin >> l >> r;
--l;
std::cout << get(l, r) << "\n";
}
}
#include <bits/stdc++.h>
using i64 = long long;
constexpr int L = 2E7 + 4;
struct Node {
int ch[2] {};
i64 s = 0;
} node[L];
int tot = 0;
int newNode(int t) {
node[++tot] = node[t];
return tot;
}
int add(int t, int l, int r, int x) {
t = newNode(t);
node[t].s += x;
if (r - l == 1) {
return t;
}
int m = (r + l) / 2;
if (x < m) {
node[t].ch[0] = add(node[t].ch[0], l, m, x);
} else {
node[t].ch[1] = add(node[t].ch[1], m, r, x);
}
return t;
}
int query(int t1, int t2, int l, int r, int x, int y) {
if (y <= l || r <= x) {
return 0;
}
if (x <= l && r <= y) {
return node[t2].s - node[t1].s;
}
int m = (l + r) / 2;
return query(node[t1].ch[0], node[t2].ch[0], l, m, x, y) + query(node[t1].ch[1], node[t2].ch[1], m, r, x, y);
}
constexpr int N = 1E9 + 4;
bool chmax(auto &x, int y) {
if (x >= y) {
return false;
}
x = y;
return true;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> a(n);
std::vector<int> rt(n + 1);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
rt[i + 1] = add(rt[i], 0, N, a[i]);
}
int m;
std::cin >> m;
auto get = [&](int l, int r) -> int {
int ans = 1;
while (chmax(ans, query(rt[l], rt[r], 0, N, 0, ans + 1) + 1))
;
return ans;
};
for (int i = 0; i < m; ++i) {
int l, r;
std::cin >> l >> r;
--l;
std::cout << get(l, r) << "\n";
}
}
其二
#include <bits/stdc++.h>
using i64 = long long;
constexpr int L = 3E7;
int tot;
struct Node {
Node *l = nullptr;
Node *r = nullptr;
int x;
} pool[L];
Node *newNode(int x = 0) {
pool[tot].x = x;
return &pool[tot++];
}
Node *newNode(Node *p) {
if (p) {
pool[tot] = *p;
}
return &pool[tot++];
}
Node *build(std::vector<int> &a) {
int n = a.size();
return [&](this auto &&self, int l, int r) -> Node * {
if (r - l == 1) {
return newNode(a[l]);
}
int m = (l + r) / 2;
auto u = newNode();
*u = {self(l, m), self(m, r), 0};
return u;
} (0, n);
}
Node *modify(Node *t, int l, int r, int p, int c) {
if (r - l == 1) {
return newNode(c);
}
t = newNode(t);
int m = (l + r) / 2;
if (p < m) {
t->l = modify(t->l, l, m, p, c);
} else {
t->r = modify(t->r, m, r, p, c);
}
return t;
}
int query(Node *t, int l, int r, int x) {
if (r - l == 1) {
return t->x;
}
int m = (l + r) / 2;
if (x < m) {
return query(t->l, l, m, x);
}
return query(t->r, m, r, x);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
std::vector<int> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
tot = 0;
std::vector<Node *> roots(m + 1);
roots[0] = build(a);
for (int i = 0; i < m; ++i) {
int v, op, p;
std::cin >> v >> op >> p;
--p;
if (op == 1) {
int c;
std::cin >> c;
roots[i + 1] = modify(roots[v], 0, n, p, c);
} else {
roots[i + 1] = roots[v];
std::cout << query(roots[i + 1], 0, n, p) << "\n";
}
}
}
动态开点 线段树
ADD
#include <bits/stdc++.h>
using i64 = long long;
constexpr int L = 1E7 + 5;
struct Node {
int l = 0, r = 0;
int v = 0;
} node[L];
int tot = 0;
int newNode(int t = 0) {
node[++tot] = node[t];
return tot;
}
void pull(int p) {
node[p].v = node[node[p].l].v + node[node[p].r].v;
}
void modify(int &t, int l, int r, int x, int v) {
if (!t) {
t = newNode();
}
if (r - l == 1) {
node[t].v = v;
return;
}
int m = (l + r) / 2;
if (x < m) {
modify(node[t].l, l, m, x, v);
} else {
modify(node[t].r, m, r, x, v);
}
pull(t);
}
int query(int t, int l, int r, int x, int y) {
if (!t) {
return 0;
}
if (y <= l || r <= x) {
return 0;
}
if (x <= l && r <= y) {
return node[t].v;
}
int m = (l + r) / 2;
return query(node[t].l, l, m, x, y) + query(node[t].r, m, r, x, y);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
std::vector<int> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
auto ord = a;
std::sort(ord.begin(), ord.end());
ord.erase(std::unique(ord.begin(), ord.end()), ord.end());
auto get = [&](int x) -> int {
return std::lower_bound(ord.begin(), ord.end(), x) - ord.begin();
};
int N = ord.size();
std::vector<int> roots(N);
for (int i = 0; i < n; ++i) {
modify(roots[get(a[i])], 0, n, i, 1);
}
while (m--) {
int o;
std::cin >> o;
if (o == 1) {
int l, r, x;
std::cin >> l >> r >> x;
--l;
if (x > ord.back() || x != ord[get(x)]) {
std::cout << 0 << "\n";
continue;
}
std::cout << query(roots[get(x)], 0, n, l, r) << "\n";
} else {
int x;
std::cin >> x;
--x;
modify(roots[get(a[x])], 0, n, x, 0);
modify(roots[get(a[x + 1])], 0, n, x + 1, 0);
std::swap(a[x], a[x + 1]);
modify(roots[get(a[x])], 0, n, x, 1);
modify(roots[get(a[x + 1])], 0, n, x + 1, 1);
}
}
}
#include <bits/stdc++.h>
using u64 = unsigned long long;
struct Info {
Info *l = nullptr;
Info *r = nullptr;
u64 tag = 0;
u64 sum = 0;
int act = 0;
};
void tag(Info *p, int k) {
p->tag += k;
p->sum += 1ULL * p->act * k;
}
void push(Info *p) {
if (!p->l) {
p->l = new Info{nullptr, nullptr, 0, 0, p->act / 2};
}
if (!p->r) {
p->r = new Info{nullptr, nullptr, 0, 0, p->act - p->act / 2};
}
tag(p->l, p->tag);
tag(p->r, p->tag);
p->tag = 0;
}
void modify(Info *p, int l, int r, int x, int y, int k) {
if (y <= l || r <= x) {
return;
}
if (x <= l && r <= y) {
tag(p, k);
return;
}
int m = (l + r) / 2;
push(p);
modify(p->l, l, m, x, y, k);
modify(p->r, m, r, x, y, k);
p->sum += 1ULL * (std::min(r, y) - std::max(l, x)) * k;
}
u64 query(Info *p, int l, int r, int x, int y) {
if (y <= l || r <= x) {
return 0;
}
if (x <= l && r <= y) {
return p->sum;
}
int m = (l + r) / 2;
push(p);
return query(p->l, l, m, x, y) + query(p->r, m, r, x ,y);
}
int main() {
int n, q;
std::cin >> n >> q;
Info *rt = new Info{nullptr, nullptr, 0, 0, n};
for (int op, l, r; q; --q) {
std::cin >> op >> l >> r;
--l;
if (op == 1) {
int k;
std::cin >> k;
modify(rt, 0, n, l, r, k);
} else {
std::cout << query(rt, 0, n, l, r) + 1ULL * (r - l) * (l + r + 1) / 2 << "\n";
}
}
}
DSU 解决单调栈
// 2023-01-03 18:00:55
// https://codeforces.com/contest/1779/submission/187755837
#include <bits/stdc++.h>
using i64 = long long;
struct DSU {
std::vector<int> f, siz;
DSU(int n) : f(n), siz(n, 1) { std::iota(f.begin(), f.end(), 0); }
int leader(int x) {
while (x != f[x]) x = f[x] = f[f[x]];
return x;
}
bool same(int x, int y) { return leader(x) == leader(y); }
bool merge(int x, int y) {
x = leader(x);
y = leader(y);
if (x == y) return false;
siz[x] += siz[y];
f[y] = x;
return true;
}
int size(int x) { return siz[leader(x)]; }
};
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n), b(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
for (int i = 0; i < n; i++) {
std::cin >> b[i];
}
int m;
std::cin >> m;
std::map<int, int> cnt;
for (int i = 0; i < m; i++) {
int x;
std::cin >> x;
cnt[x]++;
}
for (int i = 0; i < n; i++) {
if (a[i] < b[i]) {
std::cout << "NO\n";
return;
}
}
std::vector<int> p(n);
std::iota(p.begin(), p.end(), 0);
std::sort(p.begin(), p.end(), [&](int i, int j) {
return b[i] < b[j];
});
DSU dsu(n);
std::vector<int> mx(n);
for (int i = 0; i < n; i++) {
mx[i] = a[i] == b[i] ? -1 : b[i];
}
std::map<int, int> need;
for (int i = 0; i < n; i++) {
need[mx[i]]++;
}
auto merge = [&](int x, int y, int v) {
if (x < 0 || x >= n) return;
x = dsu.leader(x);
y = dsu.leader(y);
if (b[x] > v || b[y] > v) return;
if (x == y) return;
need[mx[x]]--;
need[mx[y]]--;
dsu.merge(x, y);
mx[x] = std::max(mx[x], mx[y]);
need[mx[x]]++;
};
for (int i = 0, j = 0; i < n; i = j) {
while (j < n && b[p[i]] == b[p[j]]) j++;
for (int k = i; k < j; k++) {
merge(p[k] - 1, p[k], b[p[i]]);
merge(p[k] + 1, p[k], b[p[i]]);
}
if (cnt[b[p[i]]] < need[b[p[i]]]) {
std::cout << "NO\n";
return;
}
}
std::cout << "YES\n";
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}
stk
另一道类似的题目,单调栈
//
// https://codeforces.com/contest/1904/submission/247175767
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n), b(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
for (int i = 0; i < n; i++) {
std::cin >> b[i];
}
for (int i = 0; i < n; i++) {
if (a[i] > b[i]) {
std::cout << "NO\n";
return;
}
}
std::vector<int> l(n), r(n);
std::vector<int> stk;
for (int i = 0; i < n; i++) {
while (!stk.empty() && a[stk.back()] <= a[i]) {
stk.pop_back();
}
l[i] = stk.empty() ? -1 : stk.back();
stk.push_back(i);
}
stk = {};
for (int i = n - 1; i >= 0; i--) {
while (!stk.empty() && a[stk.back()] <= a[i]) {
stk.pop_back();
}
r[i] = stk.empty() ? n : stk.back();
stk.push_back(i);
}
int j = 0;
for (int i = 0; i < n; i++) {
while (j < n && b[j] == a[i] && j > l[i] && j < r[i]) {
j++;
}
}
if (j == n) {
std::cout << "YES\n";
} else {
std::cout << "NO\n";
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}
XOR问题不用Trie
// 2022-12-13 20:14:06
// https://atcoder.jp/contests/abc281/submissions/37252293
// 2020-11-15 17:56:14
// https://codeforces.com/contest/1446/submission/98455040
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int N;
std::cin >> N;
std::vector<int> a(N);
for (int i = 0; i < N; i++) {
std::cin >> a[i];
}
std::sort(a.begin(), a.end());
auto solve = [&](auto solve, int l, int r, int k) {
if (k == 0) return 0;
int m = std::partition_point(a.begin() + l, a.begin() + r, [&](int x) { return ~x >> (k - 1) & 1; }) - a.begin();
if (l == m || m == r) return solve(solve, l, r, k - 1);
return std::min(solve(solve, l, m, k - 1), solve(solve, m, r, k - 1)) | 1 << (k - 1);
};
std::cout << solve(solve, 0, N, 30) << "\n";
return 0;
}
// 使用Trie
#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 1E7;
int tot;
int trie[N][2];
int newNode() {
++tot;
trie[tot][0] = trie[tot][1] = 0;
return tot;
}
void insert(int x) {
int p = 1;
for (int i = 30; i >= 0; --i) {
int u = x >> i & 1;
if (!trie[p][u]) {
trie[p][u] = newNode();
}
p = trie[p][u];
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
tot = 0;
newNode();
for (int x : a) {
insert(x);
}
auto dfs = [&](this auto &&self, int p, int k) -> int {
if (p == 0) {
return 0;
}
if (trie[p][0] && trie[p][1]) {
return std::min(self(trie[p][0], k - 1), self(trie[p][1], k - 1)) | 1 << k;
}
return self(std::max(trie[p][0], trie[p][1]), k - 1);
};
std::cout << dfs(1, 30);
}
Trie
// 2024-06-04 15:16:29
// https://codeforces.com/contest/1980/submission/263960334
// 2024-03-05 15:26:24
// https://codeforces.com/contest/1902/submission/235588474
constexpr int N = 1E7;
int trie[N][2];
int cnt[N][2];
int tot = 0;
int newNode() {
int x = ++tot;
trie[x][0] = trie[x][1] = 0;
cnt[x][0] = cnt[x][1] = 0;
return x;
}
void add(int x, int d, int t = 1) {
int p = 1;
cnt[p][d] += t;
for (int i = 29; i >= 0; i--) {
int u = x >> i & 1;
if (!trie[p][u]) {
trie[p][u] = newNode();
}
p = trie[p][u];
cnt[p][d] += t;
}
}
int query(int x, int d) {
int p = 1;
if (!cnt[p][d]) {
return 0;
}
int ans = 0;
for (int i = 29; i >= 0; i--) {
int u = x >> i & 1;
if (cnt[trie[p][u ^ 1]][d]) {
ans |= 1 << i;
p = trie[p][u ^ 1];
} else {
p = trie[p][u];
}
}
return ans;
}
带权DSU
#include <bits/stdc++.h>
using i64 = long long;
struct DSU {
std::vector<int> f, siz;
std::vector<i64> g;
DSU() {}
DSU(int n) {
init(n);
}
void init(int n) {
f.resize(n);
g.resize(n);
std::iota(f.begin(), f.end(), 0);
siz.assign(n, 1);
}
int find(int x) {
if (f[x] == f[f[x]]) {
return f[x];
}
int y = find(f[x]);
g[x] += g[f[x]];
f[x] = y;
return f[x];
}
bool same(int x, int y) {
return find(x) == find(y);
}
bool merge(int x, int y, int w) {
int fx = find(x);
int fy = find(y);
if (fx == fy) {
return g[x] - g[y] - w == 0;
}
siz[fx] += siz[fy];
g[fy] = g[x] - g[y] - w;
f[fy] = fx;
return true;
}
int size(int x) {
return siz[find(x)];
}
};
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<std::array<int, 3>> a(m);
for (auto &[u, v, w] : a) {
std::cin >> u >> v >> w;
--u, --v;
}
DSU dsu(n);
for (auto [u, v, w] : a) {
if (!dsu.merge(u, v, w)) {
std::cout << "NO\n";
return;
}
}
std::cout << "YES\n";
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
solve();
}
}
笛卡尔树
l 和 r 的lca 为区间RMQ
// 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;
}
std::vector<int> stk;
std::vector<int> lc(n, -1), rc(n, -1);
for (int i = 0; i < n; ++i) {
int last = -1;
while (!stk.empty() && a[stk.back()] > a[i]) {
last = stk.back();
stk.pop_back();
}
lc[i] = last;
if (stk.size()) {
rc[stk.back()] = i;
}
stk.push_back(i);
}
树状数组
#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 2E5 + 5;
std::vector<int> fen1(N), fen2(N);
int fenl[N], fenr[N];
void add(int *fen, int x, int y) {
for (int i = x + 1; i < N; i += i & -i) {
fen[i - 1] += y;
}
}
int sum(int *fen, int x) {
int res = 0;
for (int i = x; i; i = i & (i - 1)) {
res += fen[i - 1];
}
return res;
}
int rangeSum(int *fen, int l, int r) {
return sum(fen, r) - sum(fen, l);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
for (auto &x : a) {
add(fenr, x, 1);
}
i64 ans0 = 0, ans1 = 0;
for (auto &x : a) {
ans0 += 1LL * rangeSum(fenl, x + 1, N) * rangeSum(fenr, x + 1, N);
ans1 += 1LL * sum(fenl, x) * sum(fenr, x);
add(fenl, x, 1);
add(fenr, x, -1);
}
std::cout << ans0 << " " << ans1 << '\n';
}
线段树
#include <bits/stdc++.h>
using i64 = long long;
constexpr int L = 4E5 + 5;
struct Info {
i64 sum = 0;
i64 act = 1;
i64 tag = 0;
void apply(i64 add) {
sum += add * act;
tag += add;
}
} info[L];
Info operator+(Info a, Info b) {
Info c;
c.sum = a.sum + b.sum;
c.act = a.act + b.act;
return c;
}
void pull(int p) {
info[p] = info[2 * p] + info[2 * p + 1];
}
void push(int p) {
info[2 * p].apply(info[p].tag);
info[2 * p + 1].apply(info[p].tag);
info[p].tag = 0;
}
void rangeApply(int p, int l, int r, int x, int y, i64 t) {
if (y <= l || r <= x) {
return;
}
if (x <= l && r <= y) {
info[p].apply(t);
return;
}
int m = (l + r) / 2;
push(p);
rangeApply(2 * p, l, m, x, y, t);
rangeApply(2 * p + 1, m, r, x, y, t);
pull(p);
}
Info rangeQuery(int p, int l, int r, int x, int y) {
if (y <= l || r <= x) {
return Info();
}
if (x <= l && r <= y) {
return info[p];
}
push(p);
int m = (l + r) / 2;
return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
}
void out(int p, int l, int r) {
if (r - l == 1) {
std::cout << info[p].sum << " ";
return;
}
push(p);
int m = (l + r) / 2;
out(2 * p, l, m);
out(2 * p + 1, m, r);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
std::vector<Info> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i].sum;
}
// build
[&](this auto &&self, int p, int l, int r) -> void {
if (r - l == 1) {
info[p] = a[l];
return;
}
int m = (l + r) / 2;
self(2 * p, l, m);
self(2 * p + 1, m, r);
pull(p);
} (1, 0, n);
for (int i = 0; i < m; ++i) {
int op, x, y;
std::cin >> op >> x >> y;
--x;
if (op == 1) {
i64 k;
std::cin >> k;
rangeApply(1, 0, n, x, y, {k});
} else {
std::cout << rangeQuery(1, 0, n, x, y).sum << "\n";
}
}
return 0;
}
线段树二分
#include <bits/stdc++.h>
using i64 = long long;
template<class Info,
class Merge = std::plus<Info>>
struct SegmentTree {
const int n;
const Merge merge;
std::vector<Info> info;
SegmentTree(int n) : n(n), merge(Merge()), info(4 << std::__lg(n)) {}
SegmentTree(std::vector<Info> init) : SegmentTree(init.size()) {
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] = merge(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 merge(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 || !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);
}
};
struct Info {
int max = -1;
};
Info operator+(Info a, Info b) {
return {std::max(a.max, b.max)};
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<std::string> o(n);
std::vector<int> x(n), y(n);
for (int i = 0; i < n; i++) {
std::cin >> o[i] >> x[i] >> y[i];
}
auto v = x;
std::sort(v.begin(), v.end());
std::vector<std::set<int>> s(n, {-1});
SegmentTree<Info> seg(n);
for (int i = 0; i < n; i++) {
x[i] = std::lower_bound(v.begin(), v.end(), x[i]) - v.begin();
if (o[i] == "add") {
s[x[i]].insert(y[i]);
seg.modify(x[i], {*s[x[i]].rbegin()});
} else if (o[i] == "remove") {
s[x[i]].erase(y[i]);
seg.modify(x[i], {*s[x[i]].rbegin()});
} else {
int X = seg.findFirst(x[i] + 1, n, [&](auto a) {
return a.max > y[i];
});
if (X == -1) {
std::cout << -1 << "\n";
continue;
}
std::cout << v[X] << " " << *s[X].upper_bound(y[i]) << "\n";
}
}
return 0;
}
懒标记线段树
#include <bits/stdc++.h>
using i64 = long long;
constexpr int L = 4E5 + 5;
std::vector<int> len(L);
std::vector<int> cnt(L);
std::vector<int> tag(L);
void apply(int p) {
tag[p] ^= 1;
cnt[p] = len[p] - cnt[p];
}
void push(int p) {
if (tag[p] == 0) {
return;
}
tag[p] = 0;
apply(2 * p);
apply(2 * p + 1);
}
void pull(int p) {
cnt[p] = cnt[2 * p] + cnt[2 * p + 1];
// len[p] = len[2 * p] + len[2 * p + 1];
}
void modify(int p, int l, int r, int x, int y) {
if (r <= x || y <= l) {
return;
}
if (x <= l && r <= y) {
apply(p);
return;
}
push(p);
int m = (l + r) / 2;
modify(2 * p, l, m, x, y);
modify(2 * p + 1, m, r, x, y);
pull(p);
}
int query(int p, int l, int r, int x, int y) {
if (r <= x || y <= l) {
return 0;
}
if (x <= l && r <= y) {
return cnt[p];
}
push(p);
int m = (l + r) / 2;
return query(2 * p, l, m, x, y) + query(2 * p + 1, m, r, x, y);
}
auto out(int p, int l, int r) -> void {
if (r - l == 1) {
std::cout << cnt[p] << ' ';
return;
}
push(p);
int m = (l + r) / 2;
out(2 * p, l, m);
out(2 * p + 1, m, r);
if (p == 1) {
std::cout << std::endl;
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
// build
[&](this auto &&self, int p, int l, int r) -> void {
len[p] = r - l;
if (r - l == 1) {
return;
}
int m = (l + r) / 2;
self(2 * p, l, m);
self(2 * p + 1, m, r);
} (1, 0, n);
for (int i = 0; i < m; ++i) {
int c, a, b;
std::cin >> c >> a >> b;
--a;
if (c == 0) {
modify(1, 0, n, a, b);
} else {
std::cout << query(1, 0, n, a, b) << "\n";
}
}
}

随机存一些代码
浙公网安备 33010602011771号