数据结构板子合集

可并堆

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define pii pair<int, int>
#define mp make_pair
#define db double
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}
void Min(int& x, int y) {
    x = (x < y) ? x : y;
}
void Max(int& x, int y) {
    x = (x > y) ? x : y;
}
int add(int x, int y) {
    return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
    return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
    x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
    x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
    return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
    x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
    int ans = 1;
    while (y) {
        if (y & 1)
            ans = 1ll * x * ans % mod;
        x = 1ll * x * x % mod, y >>= 1;
    }
    return ans;
}
inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int n, m;
int rt[maxn], dis[maxn], ls[maxn], rs[maxn], vis[maxn];
pii val[maxn];

int find(int x) {
    if (x == rt[x])
        return x;
    return (rt[x] = find(rt[x]));
}

int merge(int x, int y) {
    if (!x || !y)
        return (x | y);
    if (val[x] > val[y])
        swap(x, y);
    rs[x] = merge(rs[x], y);
    if (dis[ls[x]] < dis[rs[x]])
        swap(ls[x], rs[x]);
    dis[x] = dis[rs[x]] + 1;
    return x;
}

signed main() {
    openfile();
    n = read(), m = read();
    for (int i = 1; i <= n; i++)
        rt[i] = i, val[i].first = read(), val[i].second = i;
    while (m--) {
        int op = read(), x, y;
        if (op == 1) {
            x = read(), y = read();
            if (vis[x] || vis[y])
                continue;
            x = find(x), y = find(y);
            if (x != y)
                rt[x] = rt[y] = merge(x, y);
        }
        else {
            x = read();
            if (vis[x]) {
                puts("-1");
                continue;
            }
            x = find(x);
            printf("%d\n", val[x].first), vis[x] = 1;
            rt[ls[x]] = rt[rs[x]] = rt[x] = merge(ls[x], rs[x]);
            ls[x] = rs[x] = dis[x] = 0;
        }
    }
    return 0;
}

可持久化并查集

#include <bits/stdc++.h>
#define N 300005
using namespace std;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
int n, m, now, to, cnt, rt[N];
struct tree {
    int ls, rs, fa, dep;
} tr[N * 20];
inline int build(int l, int r) {
    int to = ++cnt;
    if (l == r) {
        tr[to].fa = l;
        return to;
    }
    int mid = (l + r) >> 1;
    tr[to].ls = build(l, mid);
    tr[to].rs = build(mid + 1, r);
    return to;
}
inline int que(int now, int l, int r, int x) {
    if (l == r)
        return now;
    int mid = (l + r) >> 1;
    if (mid >= x)
        return que(tr[now].ls, l, mid, x);
    else
        return que(tr[now].rs, mid + 1, r, x);
}
inline int find(int now, int a) {
    int fa = que(rt[now], 1, n, a);
    if (tr[fa].fa == a)
        return fa;
    return find(now, tr[fa].fa);
}
inline int news(int now) {
    int to = ++cnt;
    tr[to] = tr[now];
    return to;
}
inline int hb(int now, int l, int r, int x, int f) {
    int to = news(now);
    if (l == r) {
        tr[to].fa = f;
        return to;
    }
    int mid = (l + r) >> 1;
    if (mid >= x)
        tr[to].ls = hb(tr[now].ls, l, mid, x, f);
    else
        tr[to].rs = hb(tr[now].rs, mid + 1, r, x, f);
    return to;
}
inline int add(int now, int l, int r, int x) {
    int to = news(now);
    if (l == r) {
        tr[to].dep++;
        return to;
    }
    int mid = (l + r) >> 1;
    if (mid >= x)
        tr[to].ls = add(tr[now].ls, l, mid, x);
    else
        tr[to].rs = add(tr[now].rs, mid + 1, r, x);
    return to;
}
inline void merge(int now, int a, int b) {
    rt[now] = rt[now - 1];
    a = find(now, a);
    b = find(now, b);
    if (tr[a].fa != tr[b].fa) {
        if (tr[a].dep > tr[b].dep)
            swap(a, b);
        rt[now] = hb(rt[now - 1], 1, n, tr[a].fa, tr[b].fa);
        if (tr[a].dep == tr[b].dep)
            rt[now] = add(rt[now], 1, n, tr[b].fa);
    }
}
inline bool pan(int now, int a, int b) {
    a = find(now, a), b = find(now, b);
    if (tr[a].fa == tr[b].fa)
        return 1;
    else
        return 0;
}
int main() {
    n = read();
    m = read();
    rt[0] = build(1, n);
    int op, a, b;
    for (int i = 1; i <= m; i++) {
        op = read();
        a = read();
        if (op == 1) {
            b = read();
            merge(i, a, b);
        }
        if (op == 2)
            rt[i] = rt[a];
        if (op == 3) {
            b = read();
            if (pan(i - 1, a, b))
                cout << 1 << "\n";
            else
                cout << 0 << "\n";
            rt[i] = rt[i - 1];
        }
    }
    return 0;
}

快速RMQ和LCA

树状数组

#include <bits/stdc++.h>
using namespace std;

#define lowbit(x) x&(-x)
const int maxn = 1e6 + 10;

template <typename T> inline void read(T& x) {
    x = 0;
    char c = getchar();
    bool f = 0;
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return;
}

int n, m;
int a[maxn];
int t[maxn];

void add(int x, int val) {
    for (; x <= n; x += lowbit(x)) {
        t[x] += val;
    }
}

int ask(int x) {
    int ans = 0;
    for (; x; x -= lowbit(x))
        ans += t[x];
    return ans;
}

int sum(int x, int y) {
    return ask(y) - ask(x - 1);
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    read(n), read(m);
    for (int i = 1; i <= n; i++)
        read(a[i]), add(i, a[i]);
    for (int i = 1; i <= m; i++) {
        int op, x, y;
        read(op), read(x), read(y);
        if (op == 1)
            add(x, y);
        if (op == 2)
            printf("%d\n", sum(x, y));
    }
    return 0;
}

线段树2

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int maxn = 1e5 + 10;

int n, m, mod;
int a[maxn];

struct tree
{
    int l, r, val, mul, add;
} t[maxn * 4];

void build(int tr, int l, int r)
{
    t[tr].l = l, t[tr].r = r, t[tr].mul = 1;
    if (l == r)
    {
        t[tr].val = a[l];
        return;
    }
    int mid = l + r >> 1;
    build(tr << 1, l, mid);
    build(tr << 1 | 1, mid + 1, r);
    t[tr].val = t[tr << 1].val + t[tr << 1 | 1].val;
    t[tr].val %= mod;
    return;
}

void pushdown(int x)
{
    t[x << 1].val = t[x << 1].val * t[x].mul + t[x].add * (t[x << 1].r - t[x << 1].l + 1);
    t[x << 1].val %= mod;
    t[x << 1 | 1].val = t[x << 1 | 1].val * t[x].mul + t[x].add * (t[x << 1 | 1].r - t[x << 1 | 1].l + 1);
    t[x << 1 | 1].val %= mod;
    (t[x << 1].mul *= t[x].mul) %= mod;
    (t[x << 1 | 1].mul *= t[x].mul) %= mod;
    t[x << 1].add = (t[x << 1].add * t[x].mul + t[x].add) % mod;
    t[x << 1 | 1].add = (t[x << 1 | 1].add * t[x].mul + t[x].add) % mod;
    t[x].mul = 1, t[x].add = 0;
    return;
}

void mul(int tr, int l, int r, int val)
{
    if (t[tr].l >= l && t[tr].r <= r)
    {
        (t[tr].val *= val) %= mod;
        (t[tr].mul *= val) %= mod;
        (t[tr].add *= val) %= mod;
        return;
    }
    pushdown(tr);
    int mid = t[tr].l + t[tr].r >> 1;
    if (l <= mid)
        mul(tr << 1, l, r, val);
    if (r > mid)
        mul(tr << 1 | 1, l, r, val);
    t[tr].val = t[tr << 1].val + t[tr << 1 | 1].val;
    t[tr].val %= mod;
    return;
}

void add(int tr, int l, int r, int val)
{
    if (t[tr].l >= l && t[tr].r <= r)
    {
        (t[tr].val += val * (t[tr].r - t[tr].l + 1)) %= mod;
        (t[tr].add += val) %= mod;
        return;
    }
    pushdown(tr);
    int mid = t[tr].l + t[tr].r >> 1;
    if (l <= mid)
        add(tr << 1, l, r, val);
    if (r > mid)
        add(tr << 1 | 1, l, r, val);
    t[tr].val = t[tr << 1].val + t[tr << 1 | 1].val;
    t[tr].val %= mod;
    return;
}

int ask(int tr, int l, int r)
{
    int ans = 0;
    if (t[tr].l >= l && t[tr].r <= r)
        return t[tr].val;
    pushdown(tr);
    int mid = t[tr].l + t[tr].r >> 1;
    if (l <= mid)
        ans += ask(tr << 1, l, r);
    if (r > mid)
        ans += ask(tr << 1 | 1, l, r);
    ans %= mod;
    return ans;
}

signed main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    ios::sync_with_stdio(false);
    cin >> n >> m >> mod;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    build(1, 1, n);
    while (m--)
    {
        int op;
        cin >> op;
        if (op == 1)
        {
            int x, y, k;
            cin >> x >> y >> k;
            mul(1, x, y, k);
        }
        if (op == 2)
        {
            int x, y, k;
            cin >> x >> y >> k;
            add(1, x, y, k);
        }
        if (op == 3)
        {
            int x, y;
            cin >> x >> y;
            cout << ask(1, x, y) << endl;
        }
    }
    return 0;
}

线段树3

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define ls (rt << 1)
#define rs (ls | 1)
const int maxn = 5e5 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}

int mul(int x, int y) {
    return 1ll * x * y % mod;
}

int add(int x, int y) {
    x += y;
    if (x >= mod)
        x -= mod;
    return x;
}

int sub(int x, int y) {
    x -= y;
    if (x < 0)
        x += mod;
    return x;
}

inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int n, q, a[maxn];

struct node {
    int mx, hmx, se, cnt;
    int sum;
    int ad1, add1, ad2, add2;
    int l, r;
} t[maxn << 2];
// mx是最大值,hmx是历史最大值,se是次大值,cnt是最大值有多少个,sum是区间和,ad1是最大值的加法标记,add1是最大值历史最大加法标记,ad2是其他的加法标记,add2是其他的历史最大加法标记

int max(int x, int y) {
    return x > y ? x : y;
}

int min(int x, int y) {
    return x < y ? x : y;
}

void pushup(int rt) {
    t[rt].sum = t[ls].sum + t[rs].sum;
    t[rt].hmx = max(t[ls].hmx, t[rs].hmx);
    if (t[ls].mx == t[rs].mx) {
        t[rt].mx = t[ls].mx;
        t[rt].cnt = t[ls].cnt + t[rs].cnt;
        t[rt].se = max(t[ls].se, t[rs].se);
    }
    if (t[ls].mx < t[rs].mx) {
        t[rt].mx = t[rs].mx;
        t[rt].cnt = t[rs].cnt;
        t[rt].se = max(t[ls].mx, t[rs].se);
    }
    if (t[rs].mx < t[ls].mx) {
        t[rt].mx = t[ls].mx;
        t[rt].cnt = t[ls].cnt;
        t[rt].se = max(t[ls].se, t[rs].mx);
    }
}

void build(int rt, int l, int r) {
    t[rt].l = l, t[rt].r = r;
    if (l == r) {
        t[rt].sum = t[rt].hmx = t[rt].mx = a[l];
        t[rt].se = -inf, t[rt].cnt = 1;
        return;
    }
    int mid = (l + r) >> 1;
    build(ls, l, mid), build(rs, mid + 1, r);
    pushup(rt);
}

void add(int rt, int k1, int kk1, int k2, int kk2) {
    t[rt].sum += t[rt].cnt * k1 + (t[rt].r - t[rt].l + 1 - t[rt].cnt) * k2;
    t[rt].hmx = max(t[rt].hmx, t[rt].mx + kk1);
    t[rt].mx += k1;
    t[rt].add1 = max(t[rt].add1, t[rt].ad1 + kk1);
    t[rt].ad1 += k1;
    t[rt].add2 = max(t[rt].add2, t[rt].ad2 + kk2);
    t[rt].ad2 += k2;
    if (t[rt].se != -inf)
        t[rt].se += k2;
}

void pushdown(int rt) {
    int tmp = max(t[ls].mx, t[rs].mx);
    if (t[ls].mx == tmp)
        add(ls, t[rt].ad1, t[rt].add1, t[rt].ad2, t[rt].add2);
    else
        add(ls, t[rt].ad2, t[rt].add2, t[rt].ad2, t[rt].add2);
    if (t[rs].mx == tmp)
        add(rs, t[rt].ad1, t[rt].add1, t[rt].ad2, t[rt].add2);
    else
        add(rs, t[rt].ad2, t[rt].add2, t[rt].ad2, t[rt].add2);
    t[rt].ad1 = t[rt].add1 = t[rt].ad2 = t[rt].add2 = 0;
}

void change1(int rt, int l, int r, int x, int y, int v) {
    if (x <= l && r <= y) {
        add(rt, v, v, v, v);
        return;
    }
    int mid = (l + r) >> 1;
    pushdown(rt);
    if (x <= mid)
        change1(ls, l, mid, x, y, v);
    if (y > mid)
        change1(rs, mid + 1, r, x, y, v);
    pushup(rt);
}

void change2(int rt, int l, int r, int x, int y, int v) {
    if (v >= t[rt].mx)
        return;
    if (x <= l && r <= y && v > t[rt].se) {
        add(rt, v - t[rt].mx, v - t[rt].mx, 0, 0);
        return;
    }
    int mid = (l + r) >> 1;
    pushdown(rt);
    if (x <= mid)
        change2(ls, l, mid, x, y, v);
    if (y > mid)
        change2(rs, mid + 1, r, x, y, v);
    pushup(rt);
}

int querysum(int rt, int l, int r, int x, int y) {
    if (x <= l && r <= y)
        return t[rt].sum;
    pushdown(rt);
    int mid = (l + r) >> 1;
    int ans = 0;
    if (x <= mid)
        ans += querysum(ls, l, mid, x, y);
    if (y > mid)
        ans += querysum(rs, mid + 1, r, x, y);
    return ans;
}

int querymax(int rt, int l, int r, int x, int y) {
    if (x <= l && r <= y)
        return t[rt].mx;
    int ans = -inf, mid = (l + r) >> 1;
    pushdown(rt);
    if (x <= mid)
        ans = max(ans, querymax(ls, l, mid, x, y));
    if (y > mid)
        ans = max(ans, querymax(rs, mid + 1, r, x, y));
    return ans;
}

int queryhmax(int rt, int l, int r, int x, int y) {
    if (x <= l && r <= y)
        return t[rt].hmx;
    pushdown(rt);
    int ans = -inf, mid = (l + r) >> 1;
    if (x <= mid)
        ans = max(ans, queryhmax(ls, l, mid, x, y));
    if (y > mid)
        ans = max(ans, queryhmax(rs, mid + 1, r, x, y));
    return ans;
}

signed main() {
    openfile();
    n = read(), q = read();
    for (int i = 1; i <= n; i++)
        a[i] = read();
    build(1, 1, n);
    while (q--) {
        int op = read(), l, r, x;
        switch (op) {
            case 1:
                l = read(), r = read(), x = read();
                change1(1, 1, n, l, r, x);
                break;
            case 2:
                l = read(), r = read(), x = read();
                change2(1, 1, n, l, r, x);
                break;
            case 3:
                l = read(), r = read();
                printf("%lld\n", querysum(1, 1, n, l, r));
                break;
            case 4:
                l = read(), r = read();
                printf("%lld\n", querymax(1, 1, n, l, r));
                break;
            case 5:
                l = read(), r = read();
                printf("%lld\n", queryhmax(1, 1, n, l, r));
                break;
        }
    }
    cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
    return 0;
}

线段树合并

#include <bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 10;

int son[maxn], dfn[maxn], dep[maxn], f[maxn], siz[maxn], top[maxn];
int n, m, cnt, ans[maxn], rt[maxn], tim;
int head[maxn], tot;

struct node {
    int y, nex;
} e[maxn << 1];

struct tree {
    int val, ans, l, r;
} t[maxn << 5];

void add(int x, int y) {
    e[++tot] = {y, head[x]};
    head[x] = tot;
}

void dfs1(int x, int fa) {
    dep[x] = dep[fa] + 1;
    siz[x] = 1;
    f[x] = fa;
    int maxx = 0;
    for (int i = head[x]; i; i = e[i].nex) {
        int v = e[i].y;
        if (v == fa)
            continue;
        dfs1(v, x);
        if (siz[v] > maxx)
            son[x] = v, maxx = siz[v];
        siz[x] += siz[v];
    }
    return;
}

void dfs2(int x, int fa, int _top) {
    dfn[x] = ++tim;
    top[x] = _top;
    if (son[x])
        dfs2(son[x], x, _top);
    for (int i = head[x]; i; i = e[i].nex) {
        int v = e[i].y;
        if (v == fa || v == son[x])
            continue;
        dfs2(v, x, v);
    }
    return;
}

int lca(int x, int y) {
    while (top[x] != top[y]) {
        if (dep[top[x]] < dep[top[y]])
            swap(x, y);
        x = f[top[x]];
    }
    if (dep[x] < dep[y])
        return x;
    return y;
}

void pushup(int rt) {
    t[rt].val = max(t[t[rt].l].val, t[t[rt].r].val);
    if (t[t[rt].l].val >= t[t[rt].r].val)
        t[rt].ans = t[t[rt].l].ans;
    else
        t[rt].ans = t[t[rt].r].ans;
}

int change(int rt, int l, int r, int pos, int num) {
    if (!rt)
        rt = ++cnt;
    if (l == r) {
        t[rt].ans = l;
        t[rt].val += num;
        return rt;
    }
    int mid = l + r >> 1;
    if (pos <= mid)
        t[rt].l = change(t[rt].l, l, mid, pos, num);
    else
        t[rt].r = change(t[rt].r, mid + 1, r, pos, num);
    pushup(rt);
    return rt;
}

int merge(int rt1, int rt2, int l, int r) {
    if (!rt1 || !rt2)
        return rt1 + rt2;
    if (l == r) {
        t[rt1].val += t[rt2].val;
        return rt1;
    }
    int mid = l + r >> 1;
    t[rt1].l = merge(t[rt1].l, t[rt2].l, l, mid);
    t[rt1].r = merge(t[rt1].r, t[rt2].r, mid + 1, r);
    pushup(rt1);
    return rt1;
}

void dfs(int x, int fa) {
    for (int i = head[x]; i; i = e[i].nex) {
        int v = e[i].y;
        if (v == fa)
            continue;
        dfs(v, x);
        rt[x] = merge(rt[x], rt[v], 1, 100000);
    }
    if (t[rt[x]].val == 0)
        ans[x] = 0;
    else
        ans[x] = t[rt[x]].ans;
    return;
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1; i < n; i++) {
        int x, y;
        cin >> x >> y;
        add(x, y);
        add(y, x);
    }
    dfs1(1, 0), dfs2(1, 0, 1);
    for (int i = 1; i <= m; ++i) {
        int x, y, z;
        cin >> x >> y >> z;
        int l = lca(x, y);
        rt[x] = change(rt[x], 1, 100000, z, 1);
        rt[y] = change(rt[y], 1, 100000, z, 1);
        rt[l] = change(rt[l], 1, 100000, z, -1);
        rt[f[l]] = change(rt[f[l]], 1, 100000, z, -1);
    }
    dfs(1, 0);
    for (int i = 1; i <= n; i++)
        cout << ans[i] << endl;
    return 0;
}

线段树分裂

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int MAXN = 200010;

int n, m, tot, cnt, seq = 1, op, x, y, z, bac[MAXN << 5], ch[MAXN << 5][2], rt[MAXN];
int val[MAXN << 5];

int newnode() {
    return (cnt ? bac[cnt--] : ++tot);
}

void del(int p) {
    bac[++cnt] = p, ch[p][0] = ch[p][1] = val[p] = 0;
    return;
}

void add(int& p, int l, int r, int pos, int v) {
    if (!p)
        p = newnode();
    val[p] += v;
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    if (pos <= mid)
        add(ch[p][0], l, mid, pos, v);
    else
        add(ch[p][1], mid + 1, r, pos, v);
    return;
}

int query(int p, int l, int r, int xl, int xr) {
    if (xr < l || r < xl)
        return 0;
    if (xl <= l && r <= xr)
        return val[p];
    int mid = (l + r) >> 1;
    return query(ch[p][0], l, mid, xl, xr) + query(ch[p][1], mid + 1, r, xl, xr);
}

int kth(int p, int l, int r, int k) {
    if (l == r)
        return l;
    int mid = (l + r) >> 1;
    if (val[ch[p][0]] >= k)
        return kth(ch[p][0], l, mid, k);
    else
        return kth(ch[p][1], mid + 1, r, k - val[ch[p][0]]);
}

int merge(int x, int y) {
    if (!x || !y)
        return x + y;
    val[x] += val[y];
    ch[x][0] = merge(ch[x][0], ch[y][0]);
    ch[x][1] = merge(ch[x][1], ch[y][1]);
    del(y);
    return x;
}

void split(int x, int& y, int k) {
    if (x == 0)
        return;
    y = newnode();
    int v = val[ch[x][0]];
    if (k > v)
        split(ch[x][1], ch[y][1], k - v);
    else
        swap(ch[x][1], ch[y][1]);
    if (k < v)
        split(ch[x][0], ch[y][0], k);
    val[y] = val[x] - k;
    val[x] = k;
    return;
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
    scanf("%lld%lld", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &x);
        add(rt[1], 1, n, i, x);
    }
    for (int i = 1; i <= m; i++) {
        scanf("%lld", &op);
        if (op == 0) {
            scanf("%lld%lld%lld", &x, &y, &z);
            int k1 = query(rt[x], 1, n, 1, z), k2 = query(rt[x], 1, n, y, z);
            int tmp = 0;
            split(rt[x], rt[++seq], k1 - k2);
            split(rt[seq], tmp, k2);
            rt[x] = merge(rt[x], tmp);
        }
        else if (op == 1) {
            scanf("%lld%lld", &x, &y);
            rt[x] = merge(rt[x], rt[y]);
        }
        else if (op == 2) {
            scanf("%lld%lld%lld", &x, &y, &z);
            add(rt[x], 1, n, z, y);
        }
        else if (op == 3) {
            scanf("%lld%lld%lld", &x, &y, &z);
            printf("%lld\n", query(rt[x], 1, n, y, z));
        }
        else if (op == 4) {
            scanf("%lld%lld", &x, &y);
            if (val[rt[x]] < y) {
                printf("-1\n");
                continue;
            }
            printf("%lld\n", kth(rt[x], 1, n, y));
        }
    }
    return 0;
}

李超线段树

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define pii pair<int, int>
#define mp make_pair
#define db double
#define ls (rt << 1)
#define rs (rt << 1 | 1)
const db eps = 1e-10;
const int maxn = 1e6 + 10;
const int mod = 39989;
const int m = 40000;
const int Mod = 1e9;
const int inf = 0x3f3f3f3f;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}
void Min(int& x, int y) {
    x = (x < y) ? x : y;
}
void Max(int& x, int y) {
    x = (x > y) ? x : y;
}
int add(int x, int y) {
    return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
    return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
    x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
    x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
    return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
    x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
    int ans = 1;
    while (y) {
        if (y & 1)
            ans = 1ll * x * ans % mod;
        x = 1ll * x * x % mod, y >>= 1;
    }
    return ans;
}
inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int n, t[maxn << 2], tot, lst;

struct line {
    db k, b;
} a[maxn];

db calc(line a, int x) {
    return a.k * x + a.b;
}

void upd(int rt, int l, int r, int x, int y, int pos) {
    int mid = (l + r) >> 1;
    if (x <= l && r <= y) {
        if (calc(a[pos], mid) > calc(a[t[rt]], mid) + eps)
            swap(pos, t[rt]);
        if (calc(a[pos], l) > calc(a[t[rt]], l) + eps ||
            (calc(a[pos], l) == calc(a[t[rt]], l) && pos < t[rt]))
            upd(ls, l, mid, x, y, pos);
        if (calc(a[pos], r) > calc(a[t[rt]], r) + eps ||
            (calc(a[pos], r) == calc(a[t[rt]], r) && pos < t[rt]))
            upd(rs, mid + 1, r, x, y, pos);
        return;
    }
    if (x <= mid)
        upd(ls, l, mid, x, y, pos);
    if (y > mid)
        upd(rs, mid + 1, r, x, y, pos);
}

int query(int rt, int l, int r, int pos) {
    if (l == r)
        return t[rt];
    int mid = (l + r) >> 1;
    if (pos <= mid) {
        int tmp = query(ls, l, mid, pos);
        db num1 = calc(a[tmp], pos), num2 = calc(a[t[rt]], pos);
        if (num1 > num2 + eps)
            return tmp;
        if (num1 + eps < num2)
            return t[rt];
        return min(tmp, t[rt]);
    }
    else {
        int tmp = query(rs, mid + 1, r, pos);
        db num1 = calc(a[tmp], pos), num2 = calc(a[t[rt]], pos);
        if (num1 > num2 + eps)
            return tmp;
        if (num1 + eps < num2)
            return t[rt];
        return min(tmp, t[rt]);
    }
}

signed main() {
    openfile();
    n = read();
    while (n--) {
        cerr << n << endl;
        int op = read();
        if (!op) {
            int k = (read() + lst - 1) % mod + 1;
            printf("%lld\n", (lst = query(1, 1, m, k)));
        }
        else {
            int x0 = (read() + lst - 1) % mod + 1, y0 = (read() + lst - 1) % Mod + 1,
                x1 = (read() + lst - 1) % mod + 1, y1 = (read() + lst - 1) % Mod + 1;
            if (x0 > x1)
                swap(x0, x1), swap(y0, y1);
            if (x0 == x1)
                a[++tot] = line{0, (db)max(y1, y0)};
            else
                a[++tot] = line{1.0 * (y1 - y0) / (x1 - x0), y0 - 1.0 * (y1 - y0) / (x1 - x0) * x0};
            upd(1, 1, m, x0, x1, tot);
        }
    }
    return 0;
}

扫描线面积

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int maxn = 2e6 + 10;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}

inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int n, tot, cnt, rk[maxn];
int t[maxn], tc[maxn];

struct line {
    int x, y, yy, z;
} e[maxn << 1];

bool cmp(line a, line b) {
    if (a.x == b.x)
        return a.z > b.z;
    return a.x < b.x;
}

void pushup(int rt, int l, int r) {
    if (!tc[rt])
        t[rt] = t[rt << 1] + t[rt << 1 | 1];
    else
        t[rt] = rk[r + 1] - rk[l];
}

void add(int rt, int l, int r, int x, int y, int val) {
    if (x <= l && r <= y) {
        tc[rt] += val;
        pushup(rt, l, r);
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid)
        add(rt << 1, l, mid, x, y, val);
    if (y > mid)
        add(rt << 1 | 1, mid + 1, r, x, y, val);
    pushup(rt, l, r);
}

signed main() {
    openfile();
    n = read();
    for (int i = 1; i <= n; i++) {
        int x = read(), y = read(), xx = read(), yy = read();
        e[++tot] = {x, y, yy, 1};
        e[++tot] = {xx, y, yy, -1};
        rk[++cnt] = y, rk[++cnt] = yy;
    }
    sort(rk + 1, rk + 1 + cnt);
    cnt = unique(rk + 1, rk + 1 + cnt) - rk - 1;
    for (int i = 1; i <= n * 2; i++) {
        e[i].y = lower_bound(rk + 1, rk + 1 + cnt, e[i].y) - rk;
        e[i].yy = lower_bound(rk + 1, rk + 1 + cnt, e[i].yy) - rk;
    }
    sort(e + 1, e + 1 + 2 * n, cmp);
    int ans = 0;
    for (int i = 1; i < 2 * n; i++) {
        add(1, 1, n * 2, e[i].y, e[i].yy - 1, e[i].z);
        ans += (e[i + 1].x - e[i].x) * t[1];
    }
    cout << ans << endl;
    return 0;
}

可持久化线段树

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define pii pair<int, int>
#define mp make_pair
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}

int add(int x, int y) {
    x += y;
    return x >= mod ? x - mod : x;
}

int sub(int x, int y) {
    x -= y;
    return x < 0 ? x + mod : x;
}

inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int n, m, a[maxn], b[maxn], cnt;
int t[maxn << 5], tot, rt[maxn << 5], ls[maxn << 5], rs[maxn << 5];

int build(int l, int r) {
    int rt = ++tot, mid = (l + r) >> 1;
    if (l == r)
        return rt;
    ls[rt] = build(l, mid), rs[rt] = build(mid + 1, r);
    return rt;
}

int add(int lst, int l, int r, int pos, int x = 1) {
    int rt = ++tot;
    t[rt] = t[lst] + x, ls[rt] = ls[lst], rs[rt] = rs[lst];
    if (l == r)
        return rt;
    int mid = (l + r) >> 1;
    if (pos <= mid)
        ls[rt] = add(ls[lst], l, mid, pos, x);
    else
        rs[rt] = add(rs[lst], mid + 1, r, pos, x);
    return rt;
}

int ask(int lr, int rr, int l, int r, int k) {
    if (l == r)
        return b[l];
    int mid = (l + r) >> 1;
    int num = t[ls[rr]] - t[ls[lr]];
    // cout << lr << ' ' << rr << ' ' << l << ' ' << r << ' ' << k << ' ' << num << endl;
    if (num >= k)
        return ask(ls[lr], ls[rr], l, mid, k);
    return ask(rs[lr], rs[rr], mid + 1, r, k - num);
}

signed main() {
    openfile();
    n = read(), m = read();
    for (int i = 1; i <= n; i++)
        a[i] = b[i] = read();
    sort(b + 1, b + 1 + n);
    cnt = unique(b + 1, b + 1 + n) - b - 1;
    rt[0] = build(1, cnt);
    for (int i = 1; i <= n; i++) {
        a[i] = lower_bound(b + 1, b + 1 + cnt, a[i]) - b;
        rt[i] = add(rt[i - 1], 1, cnt, a[i]);
    }
    while (m--) {
        int l = read(), r = read(), k = read();
        printf("%lld\n", ask(rt[l - 1], rt[r], 1, cnt, k));
    }
    cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
    return 0;
}

zkw线段树

// by Judge
#include <cstdio>
#include <iostream>
using namespace std;
const int M = 1e5 + 111;
// #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline int read() {
    int x = 0, f = 1;
    char c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (; isdigit(c); c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}
char sr[1 << 21], z[20];
int C = -1, Z;
inline void Ot() {
    fwrite(sr, 1, C + 1, stdout), C = -1;
}
inline void print(int x) {
    if (C > 1 << 20)
        Ot();
    if (x < 0)
        sr[++C] = 45, x = -x;
    while (z[++Z] = x % 10 + 48, x /= 10)
        ;
    while (sr[++C] = z[Z], --Z)
        ;
    sr[++C] = '\n';
}
int n, m, q;
int sum[M << 2], mn[M << 2], mx[M << 2], add[M << 2];
inline void build() {
    for (m = 1; m <= n; m <<= 1)
        ;
    for (int i = m + 1; i <= m + n; ++i)
        sum[i] = mn[i] = mx[i] = read();
    for (int i = m - 1; i; --i) {
        sum[i] = sum[i << 1] + sum[i << 1 | 1];
        mn[i] = min(mn[i << 1], mn[i << 1 | 1]), mn[i << 1] -= mn[i], mn[i << 1 | 1] -= mn[i];
        mx[i] = max(mx[i << 1], mx[i << 1 | 1]), mx[i << 1] -= mx[i], mx[i << 1 | 1] -= mx[i];
    }
}
inline void update_node(int x, int v, int A = 0) {
    x += m, mx[x] += v, mn[x] += v, sum[x] += v;
    for (; x > 1; x >>= 1) {
        sum[x] += v;
        A = min(mn[x], mn[x ^ 1]);
        mn[x] -= A, mn[x ^ 1] -= A, mn[x >> 1] += A;
        A = max(mx[x], mx[x ^ 1]), mx[x] -= A, mx[x ^ 1] -= A, mx[x >> 1] += A;
    }
}
inline void update_part(int s, int t, int v) {
    int A = 0, lc = 0, rc = 0, len = 1;
    for (s += m - 1, t += m + 1; s ^ t ^ 1; s >>= 1, t >>= 1, len <<= 1) {
        if (s & 1 ^ 1)
            add[s ^ 1] += v, lc += len, mn[s ^ 1] += v, mx[s ^ 1] += v;
        if (t & 1)
            add[t ^ 1] += v, rc += len, mn[t ^ 1] += v, mx[t ^ 1] += v;
        sum[s >> 1] += v * lc, sum[t >> 1] += v * rc;
        A = min(mn[s], mn[s ^ 1]), mn[s] -= A, mn[s ^ 1] -= A, mn[s >> 1] += A,
        A = min(mn[t], mn[t ^ 1]), mn[t] -= A, mn[t ^ 1] -= A, mn[t >> 1] += A;
        A = max(mx[s], mx[s ^ 1]), mx[s] -= A, mx[s ^ 1] -= A, mx[s >> 1] += A,
        A = max(mx[t], mx[t ^ 1]), mx[t] -= A, mx[t ^ 1] -= A, mx[t >> 1] += A;
    }
    for (lc += rc; s; s >>= 1) {
        sum[s >> 1] += v * lc;
        A = min(mn[s], mn[s ^ 1]), mn[s] -= A, mn[s ^ 1] -= A, mn[s >> 1] += A,
        A = max(mx[s], mx[s ^ 1]), mx[s] -= A, mx[s ^ 1] -= A, mx[s >> 1] += A;
    }
}
inline int query_node(int x, int ans = 0) {
    for (x += m; x; x >>= 1)
        ans += mn[x];
    return ans;
}
inline int query_sum(int s, int t) {
    int lc = 0, rc = 0, len = 1, ans = 0;
    for (s += m - 1, t += m + 1; s ^ t ^ 1; s >>= 1, t >>= 1, len <<= 1) {
        if (s & 1 ^ 1)
            ans += sum[s ^ 1] + len * add[s ^ 1], lc += len;
        if (t & 1)
            ans += sum[t ^ 1] + len * add[t ^ 1], rc += len;
        if (add[s >> 1])
            ans += add[s >> 1] * lc;
        if (add[t >> 1])
            ans += add[t >> 1] * rc;
    }
    for (lc += rc, s >>= 1; s; s >>= 1)
        if (add[s])
            ans += add[s] * lc;
    return ans;
}
inline int query_min(int s, int t, int L = 0, int R = 0, int ans = 0) {
    if (s == t)
        return query_node(s);
    for (s += m, t += m; s ^ t ^ 1; s >>= 1, t >>= 1) {
        L += mn[s], R += mn[t];
        if (s & 1 ^ 1)
            L = min(L, mn[s ^ 1]);
        if (t & 1)
            R = min(R, mn[t ^ 1]);
    }
    for (ans = min(L, R), s >>= 1; s; s >>= 1)
        ans += mn[s];
    return ans;
}
inline int query_max(int s, int t, int L = 0, int R = 0, int ans = 0) {
    if (s == t)
        return query_node(s);
    for (s += m, t += m; s ^ t ^ 1; s >>= 1, t >>= 1) {
        L += mx[s], R += mx[t];
        if (s & 1 ^ 1)
            L = max(L, mx[s ^ 1]);
        if (t & 1)
            R = max(R, mx[t ^ 1]);
    }
    for (ans = max(L, R), s >>= 1; s; s >>= 1)
        ans += mx[s];
    return ans;
}

signed main() {
    return 0;
}

普通平衡树(splay)

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define pii pair<int, int>
#define mp make_pair
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}

int add(int x, int y) {
    x += y;
    return x >= mod ? x - mod : x;
}

int sub(int x, int y) {
    x -= y;
    return x < 0 ? x + mod : x;
}

inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

struct Splay {
    int ch[maxn][2], tot, fa[maxn], val[maxn], cnt[maxn], siz[maxn], rt;

    int check(int x, int y) {
        return ch[y][1] == x;
    }

    void pushup(int x) {
        siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
    }

    void rotate(int x) {
        int y = fa[x], z = fa[y];
        int k = check(x, y), kk = check(y, z);
        ch[z][kk] = x, fa[x] = z;
        ch[y][k] = ch[x][k ^ 1], fa[ch[x][k ^ 1]] = y;
        fa[y] = x, ch[x][k ^ 1] = y;
        pushup(y), pushup(x);
    }

    void splay(int x, int o) {
        while (fa[x] != o) {
            int y = fa[x], z = fa[y];
            if (z != o)
                (check(x, y) ^ check(y, z)) ? rotate(x) : rotate(y);
            rotate(x);
        }
        if (!o)
            rt = x;
    }

    void insert(int x) {
        int u = rt, ff = 0;
        while (u && val[u] != x)
            ff = u, u = ch[u][x > val[u]];
        if (val[u] == x)
            cnt[u]++;
        else {
            u = ++tot;
            if (ff)
                ch[ff][x > val[ff]] = u;
            fa[u] = ff;
            val[u] = x, cnt[u] = siz[u] = 1;
        }
        splay(u, 0);
    }

    int rk(int x) {
        int u = rt;
        if (!u)
            return -1;
        while (x != val[u] && ch[u][x > val[u]])
            u = ch[u][x > val[u]];
        splay(u, 0);
        return siz[ch[u][0]] + 1;
    }

    int pre(int x) {
        rk(x);
        int u = rt;
        if (val[u] < x)
            return u;
        u = ch[u][0];
        while (ch[u][1])
            u = ch[u][1];
        return u;
    }

    int nex(int x) {
        rk(x);
        int u = rt;
        if (val[u] > x)
            return u;
        u = ch[u][1];
        while (ch[u][0])
            u = ch[u][0];
        return u;
    }

    void del(int x) {
        int l = pre(x), r = nex(x);
        splay(l, 0), splay(r, l);
        int u = ch[r][0];
        if (cnt[u] - 1)
            cnt[u]--, splay(u, 0);
        else
            ch[r][0] = 0, splay(r, 0);
    }

    int kth(int x) {
        int u = rt;
        while (1) {
            int v = ch[u][0];
            if (siz[v] + cnt[u] < x)
                x -= siz[v] + cnt[u], u = ch[u][1];
            else if (x <= siz[v])
                u = v;
            else
                return val[u];
        }
    }
} t;

signed main() {
    openfile();
    int n = read();
    t.insert(-inf), t.insert(inf);
    while (n--) {
        int op = read(), x = read();
        if (op == 1)
            t.insert(x);
        if (op == 2)
            t.del(x);
        if (op == 3)
            printf("%lld\n", t.rk(x) - 1);
        if (op == 4)
            printf("%lld\n", t.kth(x + 1));
        if (op == 5)
            printf("%lld\n", t.val[t.pre(x)]);
        if (op == 6)
            printf("%lld\n", t.val[t.nex(x)]);
    }
    cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
    return 0;
}

普通平衡树(FHQ)

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define pii pair<int, int>
#define mp make_pair
#define db double
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}
void Min(int& x, int y) {
    x = (x < y) ? x : y;
}
void Max(int& x, int y) {
    x = (x > y) ? x : y;
}
int add(int x, int y) {
    return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
    return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
    x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
    x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
    return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
    x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
    int ans = 1;
    while (y) {
        if (y & 1)
            ans = 1ll * x * ans % mod;
        x = 1ll * x * x % mod, y >>= 1;
    }
    return ans;
}
inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

mt19937 rd(time(0));
int n, tot, rt, val[maxn], pri[maxn], ls[maxn], rs[maxn], siz[maxn];

void pushup(int x) {
    siz[x] = siz[ls[x]] + siz[rs[x]] + 1;
}

int nd(int x) {
    pri[++tot] = rd(), val[tot] = x, siz[tot] = 1;
    return tot;
}

void split_siz(int rt, int k, int& x, int& y) {
    if (!rt)
        return x = y = 0, void();
    if (siz[ls[rt]] >= k) {
        y = rt;
        split_siz(ls[rt], k, x, ls[rt]);
        pushup(rt);
    }
    else {
        x = rt;
        split_siz(rs[rt], k - siz[ls[rt]] - 1, rs[rt], y);
        pushup(rt);
    }
}

void split_num(int rt, int v, int& x, int& y) {
    if (!rt)
        return x = y = 0, void();
    if (val[rt] <= v)
        x = rt, split_num(rs[x], v, rs[x], y);
    else
        y = rt, split_num(ls[y], v, x, ls[y]);
    pushup(rt);
}

int merge(int x, int y) {
    if (!x || !y)
        return (x | y);
    if (pri[x] < pri[y]) {
        rs[x] = merge(rs[x], y);
        return pushup(x), x;
    }
    else {
        ls[y] = merge(x, ls[y]);
        return pushup(y), y;
    }
}

void ins(int v) {
    int x, y;
    cerr << v << endl;
    split_num(rt, v - 1, x, y);
    rt = merge(merge(x, nd(v)), y);
}

void del(int v) {
    int x, y, z, k;
    split_num(rt, v, y, z);
    split_num(y, v - 1, x, y);
    y = merge(ls[y], rs[y]);
    rt = merge(merge(x, y), z);
}

int rk(int v) {
    int x, y, ans;
    split_num(rt, v - 1, x, y);
    ans = siz[x] + 1;
    rt = merge(x, y);
    return ans;
}

int find(int k) {
    int x, y, z, ans;
    split_siz(rt, k, y, z);
    split_siz(y, k - 1, x, y);
    ans = val[y];
    rt = merge(merge(x, y), z);
    return ans;
}

int lst(int v) {
    int x, y, ans;
    split_num(rt, v - 1, x, y);
    int u = x;
    while (rs[u])
        u = rs[u];
    ans = val[u];
    rt = merge(x, y);
    return ans;
}

int nex(int v) {
    int x, y, ans;
    split_num(rt, v, x, y);
    int u = y;
    while (ls[u])
        u = ls[u];
    ans = val[u];
    rt = merge(x, y);
    return ans;
}

signed main() {
    openfile();
    n = read();
    for (int i = 1; i <= n; i++) {
        int op = read(), x = read();
        if (op == 1)
            ins(x);
        if (op == 2)
            del(x);
        if (op == 3)
            printf("%d\n", rk(x));
        if (op == 4)
            printf("%d\n", find(x));
        if (op == 5)
            printf("%d\n", lst(x));
        if (op == 6)
            printf("%d\n", nex(x));
        cerr << i << endl;
    }
    return 0;
}

文艺平衡树(splay)

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define pii pair<int, int>
#define mp make_pair
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const ll inf = 0x3f3f3f3f3f3f3f3f;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}

int add(ll x, ll y) {
    x += y;
    return x >= mod ? x - mod : x;
}

int sub(int x, int y) {
    x -= y;
    return x < 0 ? x + mod : x;
}

inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int n, m;
int a[maxn];

struct Splay {
    int ch[maxn][2], tot, rt, fa[maxn], tag[maxn], siz[maxn], val[maxn];

    bool check(int x, int y) {
        return ch[y][1] == x;
    }

    void pushup(int x) {
        siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
    }

    void rotate(int x) {
        int y = fa[x], z = fa[y];
        int k = check(x, y), kk = check(y, z);
        fa[x] = z, ch[z][kk] = x;
        fa[ch[x][k ^ 1]] = y, ch[y][k] = ch[x][k ^ 1];
        fa[y] = x, ch[x][k ^ 1] = y;
        pushup(x), pushup(y);
    }

    void splay(int x, int o) {
        while (fa[x] != o) {
            int y = fa[x], z = fa[y];
            if (z != o)
                (check(x, y) ^ check(y, z)) ? rotate(x) : rotate(y);
            rotate(x);
        }
        if (!o)
            rt = x;
    }

    void rev(int x) {
        tag[x] ^= 1;
        swap(ch[x][0], ch[x][1]);
    }

    int build(int f, int l, int r) {
        if (r < l)
            return 0;
        int mid = (l + r) >> 1, u = ++tot;
        val[u] = mid, fa[u] = f, siz[u] = 1;
        ch[u][0] = build(u, l, mid - 1);
        ch[u][1] = build(u, mid + 1, r);
        pushup(u);
        return u;
    }

    void pushdown(int x) {
        if (tag[x]) {
            rev(ch[x][0]), rev(ch[x][1]);
            tag[x] = 0;
        }
    }

    int find(int x) {
        x++;
        int u = rt;
        while (1) {
            pushdown(u);
            int v = ch[u][0];
            if (siz[v] + 1 < x)
                x -= siz[v] + 1, u = ch[u][1];
            else if (siz[v] >= x)
                u = v;
            else
                return u;
        }
    }

    void rever(int l, int r) {
        int x = find(l - 1), y = find(r + 1);
        splay(x, 0), splay(y, x);
        rev(ch[y][0]);
    }

    void print(int x) {
        if (!x)
            return;
        pushdown(x);
        print(ch[x][0]);
        if (val[x] && val[x] <= n)
            printf("%d ", val[x]);
        print(ch[x][1]);
    }
} t;

signed main() {
    openfile();
    n = read(), m = read();
    t.rt = t.build(0, 0, n + 1);
    while (m--) {
        int x = read(), y = read();
        t.rever(x, y);
    }
    t.print(t.rt);
    cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
    return 0;
}

文艺平衡树(FHQ)

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define pii pair<int, int>
#define mp make_pair
#define db double
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}
void Min(int& x, int y) {
    x = (x < y) ? x : y;
}
void Max(int& x, int y) {
    x = (x > y) ? x : y;
}
int add(int x, int y) {
    return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
    return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
    x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
    x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
    return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
    x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
    int ans = 1;
    while (y) {
        if (y & 1)
            ans = 1ll * x * ans % mod;
        x = 1ll * x * x % mod, y >>= 1;
    }
    return ans;
}
inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int n, m, a[maxn];
int val[maxn], rev[maxn], siz[maxn], pri[maxn], ls[maxn], rs[maxn];
int tot, rt;

mt19937 rd(time(0));

int newnode(int v) {
    ++tot;
    val[tot] = v, siz[tot] = 1, pri[tot] = rd();
    return tot;
}

void fan(int rt) {
    if (rt)
        swap(ls[rt], rs[rt]), rev[rt] ^= 1;
}

void pushdown(int rt) {
    if (rev[rt])
        fan(ls[rt]), fan(rs[rt]), rev[rt] = 0;
}

void pushup(int rt) {
    siz[rt] = siz[ls[rt]] + siz[rs[rt]] + 1;
}

void split(int rt, int k, int& x, int& y) {
    if (!rt)
        return x = y = 0, void();
    pushdown(rt);
    if (siz[ls[rt]] >= k)
        y = rt, split(ls[rt], k, x, ls[rt]);
    else
        x = rt, split(rs[rt], k - siz[ls[rt]] - 1, rs[rt], y);
    pushup(rt);
}

int merge(int x, int y) {
    if (!x || !y)
        return (x | y);
    pushdown(x), pushdown(y);
    if (pri[x] < pri[y]) {
        rs[x] = merge(rs[x], y);
        pushup(x);
        return x;
    }
    else {
        ls[y] = merge(x, ls[y]);
        pushup(y);
        return y;
    }
}

void chu(int rt) {
    if (!rt)
        return;
    pushdown(rt);
    chu(ls[rt]), printf("%d ", val[rt]), chu(rs[rt]);
}

signed main() {
    openfile();
    n = read(), m = read();
    for (int i = 1; i <= n; i++)
        rt = merge(rt, newnode(i));
    while (m--) {
        int l = read(), r = read(), x, y, z;
        split(rt, r, y, z);
        split(y, l - 1, x, y);
        fan(y);
        rt = merge(merge(x, y), z);
    }
    chu(rt);
    return 0;
}

KDT

#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
using namespace std;
constexpr int MAXN = 200010;
int n, d[MAXN], lc[MAXN], rc[MAXN];
double ans = 2e18;

struct node {
  double x, y;
} s[MAXN];

double L[MAXN], R[MAXN], D[MAXN], U[MAXN];

double dist(int a, int b) {
  return (s[a].x - s[b].x) * (s[a].x - s[b].x) +
         (s[a].y - s[b].y) * (s[a].y - s[b].y);
}

bool cmp1(node a, node b) { return a.x < b.x; }

bool cmp2(node a, node b) { return a.y < b.y; }

void maintain(int x) {
  L[x] = R[x] = s[x].x;
  D[x] = U[x] = s[x].y;
  if (lc[x])
    L[x] = min(L[x], L[lc[x]]), R[x] = max(R[x], R[lc[x]]),
    D[x] = min(D[x], D[lc[x]]), U[x] = max(U[x], U[lc[x]]);
  if (rc[x])
    L[x] = min(L[x], L[rc[x]]), R[x] = max(R[x], R[rc[x]]),
    D[x] = min(D[x], D[rc[x]]), U[x] = max(U[x], U[rc[x]]);
}

int build(int l, int r) {
  if (l > r) return 0;
  if (l == r) {
    maintain(l);
    return l;
  }
  int mid = (l + r) >> 1;
  double avx = 0, avy = 0, vax = 0, vay = 0;  // average variance
  for (int i = l; i <= r; i++) avx += s[i].x, avy += s[i].y;
  avx /= (double)(r - l + 1);
  avy /= (double)(r - l + 1);
  for (int i = l; i <= r; i++)
    vax += (s[i].x - avx) * (s[i].x - avx),
        vay += (s[i].y - avy) * (s[i].y - avy);
  if (vax >= vay)
    d[mid] = 1, nth_element(s + l, s + mid, s + r + 1, cmp1);
  else
    d[mid] = 2, nth_element(s + l, s + mid, s + r + 1, cmp2);
  lc[mid] = build(l, mid - 1), rc[mid] = build(mid + 1, r);
  maintain(mid);
  return mid;
}

double f(int a, int b) {
  double ret = 0;
  if (L[b] > s[a].x) ret += (L[b] - s[a].x) * (L[b] - s[a].x);
  if (R[b] < s[a].x) ret += (s[a].x - R[b]) * (s[a].x - R[b]);
  if (D[b] > s[a].y) ret += (D[b] - s[a].y) * (D[b] - s[a].y);
  if (U[b] < s[a].y) ret += (s[a].y - U[b]) * (s[a].y - U[b]);
  return ret;
}

void query(int l, int r, int x) {
  if (l > r) return;
  int mid = (l + r) >> 1;
  if (mid != x) ans = min(ans, dist(x, mid));
  if (l == r) return;
  double distl = f(x, lc[mid]), distr = f(x, rc[mid]);
  if (distl < ans && distr < ans) {
    if (distl < distr) {
      query(l, mid - 1, x);
      if (distr < ans) query(mid + 1, r, x);
    } else {
      query(mid + 1, r, x);
      if (distl < ans) query(l, mid - 1, x);
    }
  } else {
    if (distl < ans) query(l, mid - 1, x);
    if (distr < ans) query(mid + 1, r, x);
  }
}

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  cin >> n;
  for (int i = 1; i <= n; i++) cin >> s[i].x >> s[i].y;
  build(1, n);
  for (int i = 1; i <= n; i++) query(1, n, i);
  cout << fixed << setprecision(4) << sqrt(ans) << '\n';
  return 0;
}

笛卡尔树

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define pii pair<int, int>
#define mp make_pair
#define db double
const int maxn = 1e7 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}
void Min(int& x, int y) {
    x = (x < y) ? x : y;
}
void Max(int& x, int y) {
    x = (x > y) ? x : y;
}
int add(int x, int y) {
    return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
    return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
    x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
    x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
    return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
    x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
    int ans = 1;
    while (y) {
        if (y & 1)
            ans = 1ll * x * ans % mod;
        x = 1ll * x * x % mod, y >>= 1;
    }
    return ans;
}
inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int n, a[maxn];
int sta[maxn], top, ls[maxn], rs[maxn], fa[maxn];

signed main() {
    openfile();
    n = read();
    for (int i = 1; i <= n; i++)
        a[i] = read();
    for (int i = 1; i <= n; i++) {
        int k = top;
        while (k && a[sta[k]] > a[i])
            k--;
        if (k)
            rs[sta[k]] = i, fa[i] = sta[k];
        if (k < top)
            ls[i] = sta[k + 1], fa[sta[k + 1]] = i;
        top = k;
        sta[++top] = i;
    }
    ll ans = 0;
    for (int i = 1; i <= n; i++)
        ans ^= 1ll * i * (ls[i] + 1);
    cout << ans << ' ', ans = 0;
    for (int i = 1; i <= n; i++)
        ans ^= 1ll * i * (rs[i] + 1);
    cout << ans << endl;
    return 0;
}

重剖

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define ls (rt << 1)
#define rs (rt << 1 | 1)
#define pii pair<int, int>
#define mp make_pair
const int maxn = 1e6 + 10;
const ll inf = 0x3f3f3f3f3f3f3f3f;

int n, m, rt, mod;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}

int add(ll x, ll y) {
    x += y;
    return x >= mod ? x - mod : x;
}

int sub(int x, int y) {
    x -= y;
    return x < 0 ? x + mod : x;
}

inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int dfn[maxn], siz[maxn], top[maxn], fa[maxn], son[maxn], tim, dep[maxn];
int tag[maxn << 2], t[maxn << 2], a[maxn];
vector<int> e[maxn];

void dfs1(int x, int _fa) {
    siz[x] = 1, fa[x] = _fa;
    dep[x] = dep[_fa] + 1;
    for (auto v : e[x]) {
        if (v == _fa)
            continue;
        dfs1(v, x);
        siz[x] += siz[v];
        if (siz[v] > siz[son[x]])
            son[x] = v;
    }
}

void pushdown(int rt, int l, int r) {
    if (tag[rt]) {
        int x = tag[rt], mid = (l + r) >> 1;
        t[ls] = add(t[ls], 1ll * x * (mid - l + 1) % mod),
        t[rs] = add(t[rs], 1ll * x * (r - mid) % mod), tag[rt] = 0;
        tag[ls] = add(tag[ls], x), tag[rs] = add(tag[rs], x);
    }
}

void change(int rt, int l, int r, int pos, int x) {
    if (l == r) {
        t[rt] = x;
        return;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid)
        change(ls, l, mid, pos, x);
    else
        change(rs, mid + 1, r, pos, x);
    t[rt] = add(t[ls], t[rs]);
}

void dfs2(int x, int tp) {
    dfn[x] = ++tim, top[x] = tp;
    change(1, 1, n, dfn[x], a[x]);
    if (son[x])
        dfs2(son[x], tp);
    for (auto v : e[x]) {
        if (v == fa[x] || v == son[x])
            continue;
        dfs2(v, v);
    }
}

void add(int rt, int l, int r, int x, int y, int z) {
    if (x <= l && r <= y) {
        t[rt] = add(t[rt], 1ll * z * (r - l + 1) % mod);
        tag[rt] = add(tag[rt], z);
        return;
    }
    pushdown(rt, l, r);
    int mid = (l + r) >> 1;
    if (x <= mid)
        add(ls, l, mid, x, y, z);
    if (y > mid)
        add(rs, mid + 1, r, x, y, z);
    t[rt] = add(t[ls], t[rs]);
}

int ask(int rt, int l, int r, int x, int y) {
    if (x <= l && r <= y)
        return t[rt];
    pushdown(rt, l, r);
    int ans = 0, mid = l + r >> 1;
    if (x <= mid)
        ans = add(ans, ask(ls, l, mid, x, y));
    if (y > mid)
        ans = add(ans, ask(rs, mid + 1, r, x, y));
    return ans;
}

void change_lu(int x, int y, int z) {
    while (top[x] != top[y]) {
        if (dep[top[x]] > dep[top[y]])
            swap(x, y);
        add(1, 1, n, dfn[top[y]], dfn[y], z);
        y = fa[top[y]];
        // cout << dfn[top[y]] << ' ' << dfn[y] << ' ' << z << endl;
    }
    if (dep[x] > dep[y])
        swap(x, y);
    add(1, 1, n, dfn[x], dfn[y], z);
    // cout << dfn[x] << ' ' << dfn[y] << ' ' << z << endl;
}

int ask_lu(int x, int y) {
    int ans = 0;
    while (top[x] != top[y]) {
        if (dep[top[x]] > dep[top[y]])
            swap(x, y);
        ans = add(ans, ask(1, 1, n, dfn[top[y]], dfn[y]));
        y = fa[top[y]];
    }
    if (dep[x] > dep[y])
        swap(x, y);
    ans = add(ans, ask(1, 1, n, dfn[x], dfn[y]));
    return ans;
}

void change_zi(int x, int y) {
    add(1, 1, n, dfn[x], dfn[x] + siz[x] - 1, y);
}

int ask_zi(int x) {
    return ask(1, 1, n, dfn[x], dfn[x] + siz[x] - 1);
}

signed main() {
    openfile();
    n = read(), m = read(), rt = read(), mod = read();
    for (int i = 1; i <= n; i++)
        a[i] = read();
    for (int i = 1; i < n; i++) {
        int x = read(), y = read();
        e[x].push_back(y), e[y].push_back(x);
    }
    dfs1(rt, 0), dfs2(rt, rt);
    while (m--) {
        int op = read(), x = read(), y, z;
        if (op == 1) {
            y = read(), z = read();
            change_lu(x, y, z);
        }
        if (op == 2)
            y = read(), printf("%d\n", ask_lu(x, y));
        if (op == 3)
            y = read(), change_zi(x, y);
        if (op == 4)
            printf("%d\n", ask_zi(x));
    }
    cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
    return 0;
}

长剖

#include <algorithm>
#include <iostream>
using namespace std;
constexpr int N = 1000005;

struct edge {
  int to, next;
} e[N * 2];

int head[N], tot, n;
int d[N], fa[N], mx[N];
int *f[N], g[N], mxp[N];
int dfn[N];

void add(int x, int y) {
  e[++tot] = edge{y, head[x]};
  head[x] = tot;
}

void dfs1(int x) {  // 第一次插入一个1
  d[x] = 1;
  for (int i = head[x]; i; i = e[i].next)
    if (e[i].to != fa[x]) {
      fa[e[i].to] = x;
      dfs1(e[i].to);
      d[x] = max(d[x], d[e[i].to] + 1);
      if (d[e[i].to] > d[mx[x]]) mx[x] = e[i].to;
    }
}

void dfs2(int x) {  // 第二次合并
  dfn[x] = ++*dfn;
  f[x] = g + dfn[x];
  if (mx[x]) dfs2(mx[x]);
  for (int i = head[x]; i; i = e[i].next)
    if (e[i].to != fa[x] && e[i].to != mx[x]) dfs2(e[i].to);
}

void getans(int x) {  // 暴力合并算答案
  if (mx[x]) {
    getans(mx[x]);
    mxp[x] = mxp[mx[x]] + 1;
  }
  f[x][0] = 1;
  if (f[x][mxp[x]] <= 1) mxp[x] = 0;
  for (int i = head[x]; i; i = e[i].next)
    if (e[i].to != fa[x] && e[i].to != mx[x]) {
      getans(e[i].to);
      int len = d[e[i].to];
      for (int j = 0; j <= len - 1; j++) {
        f[x][j + 1] += f[e[i].to][j];
        if (f[x][j + 1] > f[x][mxp[x]]) mxp[x] = j + 1;
        if (f[x][j + 1] == f[x][mxp[x]] && j + 1 < mxp[x]) mxp[x] = j + 1;
      }
    }
}

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  cin >> n;
  for (int i = 1; i < n; i++) {
    int x, y;
    cin >> x >> y;
    add(x, y);
    add(y, x);
  }
  dfs1(1);
  dfs2(1);
  getans(1);
  for (int i = 1; i <= n; i++) cout << mxp[i] << '\n';
}

LCT

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define pii pair<int, int>
#define mp make_pair
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif
}

int add(int x, int y) {
	x += y;
	return x >= mod ? x - mod : x;
}

int sub(int x, int y) {
	x -= y;
	return x < 0 ? x + mod : x;
}

inline int read() {
	int x = 0, f = 0;
	char c = getchar();
	while (!isdigit(c))
		f |= c == '-', c = getchar();
	while (isdigit(c))
		x = x * 10 + c - '0', c = getchar();
	if (f)
		x = -x;
	return x;
}
}  // namespace IO
using namespace IO;

int n, m;

struct LCT {
	int fa[maxn], ch[maxn][2], res[maxn], val[maxn], q[maxn], top, rev[maxn];
	// res是
	// 异或和,val每个点的值,q是splay时用于下传标记的数组,rev是翻转标记,fa就是父亲,非splay的根节点的fa就是树上的father,根节点的fa是整条链的father,ch是splay上的两个儿子

	bool isroot(int x) {
		return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
	}

	void pushdown(int x) {
		if (rev[x]) {
			rev[x] ^= 1, rev[ch[x][0]] ^= 1, rev[ch[x][1]] ^= 1;
			swap(ch[x][0], ch[x][1]);
		}
	}

	bool check(int x, int y) {
		return ch[y][1] == x;
	}

	void pushup(int x) {
		res[x] = val[x] ^ res[ch[x][0]] ^ res[ch[x][1]];
	}

	void rotate(int x) {
		int y = fa[x], z = fa[y], l = check(x, y), r = l ^ 1;
		if (!isroot(y))
			ch[z][check(y, z)] = x;
		fa[x] = z, fa[ch[x][r]] = y, ch[y][l] = ch[x][r];
		fa[y] = x, ch[x][r] = y;
		pushup(y), pushup(x);
	}

	void splay(int x) {
		top = 1, q[top] = x;
		int y = x;
		while (!isroot(y))
			q[++top] = fa[y], y = fa[y];
		for (int i = top; i; i--)
			pushdown(q[i]);
		while (!isroot(x)) {
			int y = fa[x], z = fa[y];
			if (!isroot(y))
				((check(x, y) ^ check(y, z)) ? rotate(x) : rotate(y));
			rotate(x);
		}
	}

	void access(int x) {
		for (int t = 0; x; t = x, x = fa[x])
			splay(x), ch[x][1] = t, pushup(x);
	}

	void makeroot(int x) {
		access(x);
		splay(x);
		rev[x] ^= 1;
	}

	int findroot(int x) {
		access(x), splay(x);
		while (ch[x][0])
			x = ch[x][0];
		return x;
	}

	void split(int x, int y) {
		makeroot(x);
		access(y);
		splay(y);
	}

	void cut(int x, int y) {
		split(x, y);
		if (ch[y][0] == x)
			ch[y][0] = 0, fa[x] = 0;
	}

	void link(int x, int y) {
		makeroot(x);
		if (findroot(y) == x)
			return;
		fa[x] = y;
	}

	int ask(int x, int y) {
		split(x, y);
		return res[y];
	}

	void change(int x, int y) {
		access(x), splay(x);
		val[x] = y, pushup(x);
	}
} lct;

signed main() {
	// ios::sync_with_stdio(false);
	// cin.tie(0);
	openfile();
	n = read(), m = read();
	for (int i = 1; i <= n; i++)
		lct.val[i] = lct.res[i] = read();
	while (m--) {
		int op = read(), x = read(), y = read();
		if (op == 0)
			printf("%d\n", lct.ask(x, y));
		if (op == 1)
			lct.link(x, y);
		if (op == 2)
			lct.cut(x, y);
		if (op == 3)
			lct.change(x, y);
	}
	return 0;
}

dsu on tree

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int maxn = 1e6 + 10;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}

inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int n;
int a[maxn], ans[maxn], son[maxn], siz[maxn], f[maxn], cnt[maxn], now, mx;
vector<int> e[maxn];

void dfs(int x, int fa) {
    f[x] = fa;
    siz[x] = 1;
    for (auto v : e[x]) {
        if (v == fa)
            continue;
        dfs(v, x);
        siz[x] += siz[v];
        if (siz[v] > siz[son[x]])
            son[x] = v;
    }
}

void clear(int x) {
    mx = now = 0;
    cnt[a[x]] = 0;
    for (auto v : e[x])
        if (v != f[x])
            clear(v);
}

void solve(int x) {
    cnt[a[x]]++;
    if (cnt[a[x]] == mx)
        now += a[x];
    if (cnt[a[x]] > mx)
        mx = cnt[a[x]], now = a[x];
}

void calc(int x) {
    solve(x);
    for (auto v : e[x])
        if (v != f[x])
            calc(v);
}

void dsu(int x) {
    for (auto v : e[x])
        if (v != f[x] && v != son[x])
            dsu(v), clear(v);
    if (son[x])
        dsu(son[x]);
    for (auto v : e[x])
        if (v != f[x] && v != son[x])
            calc(v);
    solve(x);
    ans[x] = now;
}

signed main() {
    openfile();
    n = read();
    for (int i = 1; i <= n; i++)
        a[i] = read();
    for (int i = 1; i < n; i++) {
        int x = read(), y = read();
        e[x].push_back(y), e[y].push_back(x);
    }
    dfs(1, 0);
    dsu(1);
    for (int i = 1; i <= n; i++)
        printf("%lld ", ans[i]);
    cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
    return 0;
}

虚树(消耗战)

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int maxn = 1e6 + 10;

int n, m;
int head[maxn], tot;
int dfn[maxn], top[maxn], dep[maxn], siz[maxn], fa[maxn], son[maxn], cnt;
int a[maxn], k, f[maxn];
int sta[maxn], ding;
vector<int> v[maxn];

struct node {
    int y, z, nex;
} e[maxn];

void dfs1(int x, int _fa) {
    siz[x] = 1;
    fa[x] = _fa;
    dep[x] = dep[_fa] + 1;
    int maxx = 0;
    for (int i = head[x]; i; i = e[i].nex) {
        int v = e[i].y;
        if (v == _fa)
            continue;
        f[v] = min(f[x], e[i].z);
        dfs1(v, x);
        siz[x] += siz[v];
        if (siz[v] > maxx)
            maxx = siz[v], son[x] = v;
    }
}

void dfs2(int u, int fr) {
    top[u] = fr, dfn[u] = ++cnt;
    if (!son[u])
        return;
    dfs2(son[u], fr);
    for (int i = head[u]; i; i = e[i].nex) {
        int v = e[i].y;
        if (v != fa[u] && v != son[u])
            dfs2(v, v);
    }
}

int lca(int a, int b) {
    while (top[a] != top[b])
        dep[top[a]] > dep[top[b]] ? a = fa[top[a]] : b = fa[top[b]];
    return dep[a] < dep[b] ? a : b;
}

void add(int x, int y, int z) {
    e[++tot] = {y, z, head[x]};
    head[x] = tot;
}

bool cmp(int x, int y) {
    return dfn[x] < dfn[y];
}

void add(int x) {
    if (ding == 1) {
        sta[++ding] = x;
        return;
    }
    int l = lca(x, sta[ding]);
    if (l == sta[ding])
        return;
    while (ding > 1 && dfn[sta[ding - 1]] >= dfn[l])
        v[sta[ding - 1]].push_back(sta[ding]), --ding;
    if (sta[ding] != l)
        v[l].push_back(sta[ding]), sta[ding] = l;
    sta[++ding] = x;
}

int dp(int u) {
    if (v[u].size() == 0)
        return f[u];
    int temp = 0;
    for (int i = 0; i < v[u].size(); ++i)
        temp += dp(v[u][i]);
    v[u].clear();
    return min(f[u], temp);
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i < n; i++) {
        int x, y, z;
        cin >> x >> y >> z;
        add(x, y, z);
        add(y, x, z);
    }
    f[1] = 0x3f3f3f3f3f3f3f3f;
    dfs1(1, 0), dfs2(1, 1);
    cin >> m;
    while (m--) {
        cin >> k;
        for (int i = 1; i <= k; ++i)
            cin >> a[i];
        sort(a + 1, a + k + 1, cmp);
        sta[ding = 1] = 1;
        for (int i = 1; i <= k; ++i)
            add(a[i]);
        while (ding)
            v[sta[ding - 1]].push_back(sta[ding]), --ding;
        cout << dp(1) << endl;
    }
    return 0;
}

点分治1

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define pii pair<int, int>
#define mp make_pair
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const ll inf = 0x3f3f3f3f3f3f3f3f;

namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
}

int mul(int x, int y) {
    return 1ll * x * y % mod;
}

int add(ll x, ll y) {
    x += y;
    if (x >= mod)
        x -= mod;
    return x;
}

int sub(int x, int y) {
    return add(x, mod - y);
}

inline int read() {
    int x = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    if (f)
        x = -x;
    return x;
}
}  // namespace IO
using namespace IO;

int n, m, wen[maxn], ans[maxn];
int b[maxn], d[maxn], root, vis[maxn];
int siz[maxn], mx[maxn], t[maxn], cnt, col[maxn];
vector<pii> e[maxn];

void getroot(int x, int fa, int tot) {
    siz[x] = 1;
    mx[x] = 0;
    for (auto vv : e[x]) {
        int v = vv.first;
        if (v == fa || vis[v])
            continue;
        getroot(v, x, tot);
        siz[x] += siz[v];
        mx[x] = max(mx[x], siz[v]);
    }
    mx[x] = max(mx[x], tot - siz[x]);
    if (mx[x] < mx[root] || !root)
        root = x;
}

void getdis(int x, int fa, int dis, int color) {
    t[++cnt] = x;
    d[x] = dis;
    col[x] = color;
    for (auto vv : e[x]) {
        int v = vv.first, z = vv.second;
        if (v == fa || vis[v])
            continue;
        getdis(v, x, dis + z, color);
    }
}

bool cmp(int x, int y) {
    return d[x] < d[y];
}

void calc(int x) {
    cnt = 1;
    t[cnt] = x;
    d[x] = 0;
    col[x] = x;
    for (auto vv : e[x]) {
        int v = vv.first, z = vv.second;
        if (vis[v])
            continue;
        getdis(v, x, z, v);
    }
    sort(t + 1, t + 1 + cnt, cmp);
    for (int i = 1; i <= m; i++) {
        int l = 1, r = cnt;
        if (ans[i])
            continue;
        while (l < r) {
            if (d[t[l]] + d[t[r]] > wen[i])
                r--;
            else if (d[t[l]] + d[t[r]] < wen[i])
                l++;
            else if (col[t[l]] == col[t[r]])
                if (d[t[l]] == d[t[l + 1]])
                    l++;
                else
                    r--;
            else {
                ans[i] = 1;
                break;
            }
        }
    }
}

void solve(int x) {
    vis[x] = 1;
    calc(x);
    for (auto vv : e[x]) {
        int v = vv.first;
        if (vis[v])
            continue;
        root = 0;
        getroot(v, 0, siz[v]);
        getroot(root, 0, siz[v]);
        solve(root);
    }
}

signed main() {
    openfile();
    n = read(), m = read();
    for (int i = 1; i < n; i++) {
        int x = read(), y = read(), z = read();
        e[x].push_back(mp(y, z));
        e[y].push_back(mp(x, z));
    }
    for (int i = 1; i <= m; i++)
        wen[i] = read();
    getroot(1, 0, n);
    solve(root);
    for (int i = 1; i <= m; i++)
        if (ans[i])
            puts("AYE");
        else
            puts("NAY");
    cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
    return 0;
}

动态点分治(捉迷藏)

#include <bits/stdc++.h>
using namespace std;
#define void inline void
#define int long long
const int maxn = 1e5 + 10;
int n;
int ques;
int now[maxn], d[maxn];
int mx[maxn], siz[maxn], f[maxn][31], root;
int par[maxn];
bool vis[maxn];
int num;

namespace IO
{
    template <typename T>
    void read(T &x)
    {
        x = 0;
        bool f = 0;
        char c = getchar();
        while (!isdigit(c))
            f |= c == '-', c = getchar();
        while (isdigit(c))
            x = x * 10 + c - '0', c = getchar();
        if (f)
            x = -x;
    }

    template <typename T, typename... Args>
    void read(T &x, Args &...args) { read(x), read(args...); }

    template <typename T>
    void write(T x)
    {
        if (x < 0)
            putchar('-'), x = -x;
        if (x > 9)
            write(x / 10);
        putchar('0' + x % 10);
    }
}
using namespace IO;
struct que
{
    priority_queue<int> x, y;
    void push(int a) { x.push(a); }
    void del(int a) { y.push(a); }
    int top()
    {
        while (y.size() && x.top() == y.top())
            x.pop(), y.pop();
        return x.top();
    }
    int size() { return x.size() - y.size(); }
    void pop()
    {
        while (y.size() && x.top() == y.top())
            x.pop(), y.pop();
        x.pop();
    }
    int sectop()
    {
        int a = top();
        pop();
        int b = top();
        push(a);
        return b;
    }
} q, q1[maxn], q2[maxn];
struct node
{
    int y, nex;
} e[maxn * 2];
int head[maxn], tot;
void add(int x, int y)
{
    e[++tot] = {y, head[x]};
    head[x] = tot;
}
void dfs(int x, int fa)
{
    d[x] = d[fa] + 1;
    siz[x] = 1;
    f[x][0] = fa;
    for (int i = 1; i <= 20; i++)
        f[x][i] = f[f[x][i - 1]][i - 1];
    for (int i = head[x]; i; i = e[i].nex)
    {
        int v = e[i].y;
        if (v == fa)
            continue;
        dfs(v, x);
        siz[x] += siz[v];
    }
    return;
}
int lca(int x, int y)
{
    if (x == y)
        return x;
    if (d[x] > d[y])
        swap(x, y);
    for (int i = 20; i >= 0; i--)
        if (d[f[y][i]] >= d[x])
            y = f[y][i];
    if (x == y)
        return x;
    for (int i = 20; i >= 0; i--)
        if (f[x][i] != f[y][i])
            x = f[x][i], y = f[y][i];
    return f[x][0];
}
int dis(int x, int y)
{
    return d[x] + d[y] - 2 * d[lca(x, y)];
}
void getroot(int x, int fa, int size_)
{
    siz[x] = 1;
    mx[x] = 0;
    for (int i = head[x]; i; i = e[i].nex)
    {
        int v = e[i].y;
        if (vis[v] || v == fa)
            continue;
        getroot(v, x, size_);
        siz[x] += siz[v];
        mx[x] = max(mx[x], siz[v]);
    }
    mx[x] = max(mx[x], size_ - siz[x]);
    if (!root || mx[root] > mx[x])
        root = x;
}
void calc(int x, int fa)
{
    q2[root].push(dis(x, par[root]));
    siz[x] = 1;
    for (int i = head[x]; i; i = e[i].nex)
    {
        int v = e[i].y;
        if (vis[v] || v == fa)
            continue;
        calc(v, x);
        siz[x] += siz[v];
    }
    return;
}
void Del(int x)
{
    if (q1[x].size() >= 2)
        q.del(q1[x].top() + q1[x].sectop());
}
void Ins(int x)
{
    if (q1[x].size() >= 2)
        q.push(q1[x].top() + q1[x].sectop());
}
void build(int x, int fa)
{
    vis[x] = 1, q1[x].push(0);
    par[x] = fa;
    calc(x, 0);
    for (int i = head[x]; i; i = e[i].nex)
    {
        int v = e[i].y;
        if (vis[v])
            continue;
        root = 0;
        getroot(v, 0, siz[v]);
        build(v = root, x);
        q1[x].push(q2[v].top());
    }
    return Ins(x);
}
void change(int x)
{
    if (!now[x])
    {
        num--, Del(x), q1[x].del(0), Ins(x);
        for (int i = x; par[i]; i = par[i])
        {
            Del(par[i]);
            q1[par[i]].del(q2[i].top());
            q2[i].del(dis(x, par[i]));
            if (q2[i].size())
                q1[par[i]].push(q2[i].top());
            Ins(par[i]);
        }
    }
    else
    {
        num++, Del(x), q1[x].push(0), Ins(x);
        for (int i = x; par[i]; i = par[i])
        {
            Del(par[i]);
            if (q2[i].size())
                q1[par[i]].del(q2[i].top());
            q2[i].push(dis(x, par[i]));
            q1[par[i]].push(q2[i].top());
            Ins(par[i]);
        }
    }
    now[x] ^= 1;
    return;
}
int ask()
{
    if (num < 2)
        return num - 1;
    return q.top();
}
signed main()
{
    read(n);
    num = n;
    for (int i = 1; i < n; i++)
    {
        int x, y;
        read(x, y);
        add(x, y);
        add(y, x);
    }
    dfs(1, 0);
    getroot(1, 0, n);
    build(root, 0);
    read(ques);
    while (ques--)
    {
        char op;
        int x;
        scanf("%s", &op);
        if (op == 'C')
        {
            read(x);
            change(x);
        }
        else
            write(ask()), putchar('\n');
    }
    return 0;
}

哈希表

constexpr int SIZE = 1000000;
constexpr int M = 999997;

struct HashTable {
  struct Node {
    int next, value, key;
  } data[SIZE];

  int head[M], size;

  int f(int key) { return (key % M + M) % M; }

  int get(int key) {
    for (int p = head[f(key)]; p; p = data[p].next)
      if (data[p].key == key) return data[p].value;
    return -1;
  }

  int modify(int key, int value) {
    for (int p = head[f(key)]; p; p = data[p].next)
      if (data[p].key == key) return data[p].value = value;
  }

  int add(int key, int value) {
    if (get(key) != -1) return -1;
    data[++size] = Node{head[f(key)], value, key};
    head[f(key)] = size;
    return value;
  }
};
struct hash_map {  // 哈希表模板

  struct data {
    long long u;
    int v, nex;
  };  // 前向星结构

  data e[SZ << 1];  // SZ 是 const int 表示大小
  int h[SZ], cnt;

  int hash(long long u) { return (u % SZ + SZ) % SZ; }

  // 这里使用 (u % SZ + SZ) % SZ 而非 u % SZ 的原因是
  // C++ 中的 % 运算无法将负数转为正数

  int& operator[](long long u) {
    int hu = hash(u);  // 获取头指针
    for (int i = h[hu]; i; i = e[i].nex)
      if (e[i].u == u) return e[i].v;
    return e[++cnt] = data{u, -1, h[hu]}, h[hu] = cnt, e[cnt].v;
  }

  hash_map() {
    cnt = 0;
    memset(h, 0, sizeof(h));
  }
};
posted @ 2025-09-01 23:51  Johnsonloy  阅读(17)  评论(0)    收藏  举报