模板集合(持续更新中)
线段树
// 线段树
namespace Seg_tree {
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid ((l + r) >> 1)
typedef long long ll;
const int N = 1e5 + 5;
using std::max;
using std::min;
ll val[N << 2], laz[N << 2], maxx[N << 2], minn[N << 2];
template<class T>
const T& _max(const T& a, const T& b) { // 比较函数
return a > b ? a : b;
}
template<class T>
const T& _min(const T& a, const T& b) { // 比较函数
return a > b ? b : a;
}
void pushup(int u) { // 更新信息
val[u] = val[ls] + val[rs];
maxx[u] = max(maxx[ls], maxx[rs]);
minn[u] = min(minn[ls], minn[rs]);
}
void pushdown(int u, int l, int r) { // 下传标记
if (!laz[u]) return ;
laz[ls] += laz[u];
val[ls] += laz[u] * (mid - l + 1);
maxx[ls] += laz[u] * (mid - l + 1);
minn[ls] += laz[u] * (mid - l + 1);
laz[rs] += laz[u];
val[rs] += laz[u] * (r - mid);
maxx[rs] += laz[u] * (r - mid);
minn[rs] += laz[u] * (r - mid);
laz[u] = 0;
}
void build(int u, int l, int r) { // 建树
laz[u] = 0;
if (l == r) {
scanf("%lld", &val[u]);
maxx[u] = minn[u] = val[u];
return ;
}
build(ls, l, mid);
build(rs, mid + 1, r);
pushup(u);
}
void add(int u, int l, int r, int lr, int rr, ll c) { // 区间加减
if (lr <= l && r <= rr) {
laz[u] += c;
ll tmp = (r - l + 1) * c;
val[u] += tmp;
minn[u] += tmp;
maxx[u] += tmp;
return ;
}
pushdown(u, l, r);
if (lr <= mid) add(ls, l, mid, lr, rr, c);
if (rr > mid) add(rs, mid + 1, r, lr, rr, c);
pushup(u);
}
ll qry(int u, int l, int r, int lr, int rr, ll* g) { // 区间查询,g 为查询的数组名
if (lr <= l && r <= rr) {
return g[u];
}
pushdown(u, l, r);
ll ans = 0;
if (lr <= mid) {
ans += qry(ls, l, mid, lr, rr, g);
}
if (rr > mid) {
ans += qry(rs, mid + 1, r, lr, rr, g);
}
return ans;
}
}
ST 表
namespace ST_RMQ {
#define MAX 1
#define MIN 0
typedef long long ll;
const int N = 1e5 + 5;
using std::max;
using std::min;
int lg[N];
ll maxx[N][20], minn[N][20];
template<class T>
const T& _max(const T& a, const T& b) {
return a > b ? a : b;
}
template<class T>
const T& _min(const T& a, const T& b) {
return a > b ? b : a;
}
void pre(int n) { // 预处理 lg
for (int i = 2; i <= n; ++ i) {
lg[i] = lg[i >> 1] + 1;
}
}
void work(int n) {
for (int j = 1; j <= lg[n]; ++ j) {
for (int i = 1; i + (1 << j) - 1 <= n; ++ i) {
maxx[i][j] = max(maxx[i][j - 1], maxx[i + (1 << j - 1)][j - 1]);
minn[i][j] = min(minn[i][j - 1], minn[i + (1 << j - 1)][j - 1]);
}
}
}
ll qry(int l, int r, int fg) { // 求最值,fg 为 1 时求最大值,fg 为 2 时求最小值
int k = lg[r - l + 1];
if (fg == MAX) return max(maxx[l][k], maxx[r - (1 << k) + 1][k]);
if (fg == MIN) return min(minn[l][k], minn[r - (1 << k) + 1][k]);
return -1;
}
}
堆
// 堆
namespace Heap {
typedef long long ll;
using std::priority_queue;
using std::vector;
using std::queue;
using std::greater;
using std::swap;
const int N = 1e5 + 5;
// 对顶堆
struct top_heap {
priority_queue<ll> q1;
priority_queue<ll, vector<ll>, greater<ll> > q2;
void insert(ll x) { // 插入
if (q1.empty()) {
q1.push(x);
return ;
}
if(x > q1.top()) q2.push(x);
else q1.push(x);
}
int K_th(int k) { // 求第 K 大的值
if (q1.size() + q2.size() < k) return -1;
while (q1.size() < k) {
q1.push(q2.top());
q2.pop();
}
while (q1.size() > k) {
q2.push(q1.top());
q1.pop();
}
return q1.top();
}
int pop_K_th(int k) { // 删除第 K 大的值
if (q1.size() + q2.size() < k) return -1;
while (q1.size() < k) {
q1.push(q2.top());
q2.pop();
}
while (q1.size() > k) {
q2.push(q1.top());
q1.pop();
}
int u = q1.top();
q1.pop();
return u;
}
};
// 可删除堆
struct del_heap {
priority_queue<ll, vector<ll>, greater<ll> > q1, q2;
void insert(ll x) { // 插入
q1.push(x);
}
void del(ll x) { // 删除
q2.push(x);
}
ll top() { // 取堆顶
while(!q2.empty() && !q1.empty() && q2.top() == q1.top()) {
q1.pop(), q2.pop();
}
return q1.top();
}
};
// 左偏树(小根堆)
struct leftist_tree {
int lson[N], rson[N], fa[N], fat[N];
ll val[N], dist[N];
int merge(int x, int y) { // 合并
if (!x || !y) {
return x | y;
}
if (val[x] > val[y] || (val[x] == val[y] && x > y))
swap(x, y);
rson[x] = merge(rson[x], y);
fat[rson[x]] = fa[rson[x]] = x;
if (dist[lson[x]] < dist[rson[x]])
swap(lson[x], rson[x]);
dist[x] = dist[rson[x]] + 1;
return x;
}
int find(int u) { // 查询堆顶的元素的标号
return (fat[u] == u || fat[u] == 0) ? u : fat[u] = find(fat[u]);
}
void earse(int u) { // 删除任意一点
int tmp = merge(lson[u], rson[u]), fu = fa[u];
fat[tmp] = fa[tmp] = fu;
fat[u] = fa[u] = tmp;
lson[fu] == u ? lson[fu] = tmp : rson[fu] = tmp;
while (fu) {
if (dist[lson[fu]] < dist[rson[fu]])
swap(lson[fu], rson[fu]);
if (dist[fu] == dist[rson[fu]] + 1)
return ;
dist[fu] = dist[rson[fu]] + 1;
fu = fa[fu];
}
}
ll top(int u) { // 查询 u 点所在堆的堆顶元素
int g = find(u);
return val[g];
}
void pop(int u) { // 弹出 u 点所在对的堆顶元素
int g = find(u);
earse(g);
}
int build(int n) { // 建树
queue<int> q;
for (int i = 1; i <= n; ++ i) {
q.push(i);
}
int x, y, z;
while (q.size() > 1) {
x = q.front(), q.pop();
y = q.front(), q.pop();
z = merge(x, y), q.push(z);
}
return q.front();
}
};
}
平衡树(FHQ)
// 平衡树(FHQ)
namespace Balance_tree {
#define lc ch[u][0]
#define rc ch[u][1]
const int N = 1e5 + 5;
struct FHQ {
int cnt, rt, top;
int ch[N][2], siz[N], val[N], pai[N], rub[N];
void pushup(int u) {
siz[u] = siz[lc] + siz[rc] + 1;
return ;
}
int New(int c) {
int u;
if (!top) {
u = ++ cnt;
}
else {
u = rub[top];
top --;
}
val[u] = c;
siz[u] = 1;
pai[u] = rand();
lc = 0, rc = 0;
return u;
}
void split1(int u, int c, int &x, int &y) { // 按照权值分裂
if (u == 0) {
x = y = 0;
return ;
}
if (val[u] <= c) {
x = u;
split1(rc, c, rc, y);
}
else {
y = u;
split1(lc, c, x, lc);
}
pushup(u);
}
void split2(int u, int k, int &x, int &y) { // 按照子树大小分裂
if (u == 0) {
x = y = 0;
return ;
}
pushup(u);
if (siz[lc] + 1 <= k) {
x = u;
split2(rc, k - siz[lc] - 1, rc, y);
}
else {
y = u;
split2(lc, k, x, lc);
}
pushup(u);
}
int merge(int x, int y) {
if (!x || !y) {
return x + y;
}
if (pai[x] < pai[y]) {
ch[x][1] = merge(ch[x][1], y);
pushup(x);
return x;
}
else {
ch[y][0] = merge(x, ch[y][0]);
pushup(y);
return y;
}
}
void insert(int c) {
int t1, t2;
split1(rt, c, t1, t2);
rt = merge(merge(t1, New(c)), t2);
}
void del(int c) {
int t1, t2, t3;
split1(rt, c, t1, t2);
split1(t1, c - 1, t1, t3);
rub[++ top] = t3;
t3 = merge(ch[t3][0], ch[t3][1]);
rt = merge(merge(t1, t3), t2);
}
int ranking(int c) {
int t1, t2, k;
split1(rt, c - 1, t1, t2);
k = siz[t1] + 1;
rt = merge(t1, t2);
return k;
}
int K_th(int k) {
int t1, t2, t3, c;
split2(rt, k, t1, t2);
split2(t1, k - 1, t1, t3);
c = val[t3];
rt = merge(merge(t1, t3), t2);
return c;
}
int pre(int c) {
int t1, t2, t3, k;
split1(rt, c - 1, t1, t2);
split2(t1, siz[t1] - 1, t1, t3);
k = val[t3];
rt = merge(merge(t1, t3), t2);
return k;
}
int nxt(int c) {
int t1, t2, t3, k;
split1(rt, c, t1, t2);
split2(t2, 1, t2, t3);
k = val[t2];
rt = merge(t1, merge(t2, t3));
return k;
}
};
}
可持久化数据结构
namespace Persistent { // 可持久化数据结构
#define mid ((l + r) >> 1)
const int N = 1e6 + 5;
const int M = (N << 5) + 10;
struct persistent_arr { // 可持久化数组
int rot;
struct node {
int ls, rs, val;
} nod[(N << 5) + 10];
inline int newnod(int u) { // 创建新节点
++ rot;
nod[rot] = nod[u];
return rot;
}
int build(int l, int r) { // 建树
int u = ++ rot;
if (l == r) {
scanf("%d", &nod[u].val);
return u;
}
nod[u].ls = build(l, mid);
nod[u].rs = build(mid + 1, r);
return u;
}
int modify(int u, int l, int r, int pos, int c) { // 修改
u = newnod(u);
if (l == r) {
nod[u].val = c;
}
else {
if (pos <= mid) {
nod[u].ls = modify(nod[u].ls, l, mid, pos, c);
}
else {
nod[u].rs = modify(nod[u].rs, mid + 1, r, pos, c);
}
}
return u;
}
int query(int u, int l, int r, int pos) { // 查询
if (l == r) {
return nod[u].val;
}
else {
if (pos <= mid) {
return query(nod[u].ls, l, mid, pos);
}
else {
return query(nod[u].rs, mid + 1, r, pos);
}
}
}
};
struct persistent_seg {
int rot;
struct node {
int l, r, val;
} nod[M];
inline int newnod(int u) { // 创建新节点
++ rot;
nod[rot] = nod[u];
nod[rot].val = nod[u].val + 1;
return rot;
}
int build(int l, int r) { // 建树
int u = ++ rot;
if (l == r) {
return u;
}
nod[u].l = build(l, mid);
nod[u].r = build(mid + 1, r);
return u;
}
int add(int u, int l, int r, int pos) { // 插入新节点
u = newnod(u);
if (l == r) return u;
if (pos <= mid) {
nod[u].l = add(nod[u].l, l, mid, pos);
}
else {
nod[u].r = add(nod[u].r, mid + 1, r, pos);
}
return u;
}
int query(int l, int r, int lr, int rr, int k) { // 查找第 k 大的值
int x = nod[nod[rr].l].val - nod[nod[lr].l].val;
if (l == r) return l;
if (k <= x) {
return query(l, mid, nod[lr].l, nod[rr].l, k);
}
else {
return query(mid + 1, r, nod[lr].r, nod[rr].r, k - x);
}
}
};
}
朝气蓬勃 后生可畏