模板合集

轻重链剖分

// time : 20210103
// test on https://www.luogu.com.cn/problem/P3384

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 100001

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

int n, m, r, p, a[M], dfn[M], pre[M], size[M];

namespace Seg {
    #define lson now << 1
    #define rson now << 1 | 1
    struct Node {
        int l, r, w, lazy;
    }tree[M << 2];
    void build(int l, int r, int now) {
        tree[now].l = l, tree[now].r = r;
        if (tree[now].l == tree[now].r) {
            tree[now].w = a[pre[l]]; return;
        }
        int mid = (tree[now].l + tree[now].r) >> 1;
        build(l, mid, lson), build(mid + 1, r, rson);
        tree[now].w = (tree[lson].w + tree[rson].w) % p;
    }
    void pushdown(int now) {
        if (tree[now].l == tree[now].r) return;
        tree[lson].lazy = (tree[lson].lazy + tree[now].lazy) % p;
        tree[rson].lazy = (tree[rson].lazy + tree[now].lazy) % p;
        tree[lson].w = (tree[lson].w + 1ll * (tree[lson].r - tree[lson].l + 1) * tree[now].lazy % p) % p;
        tree[rson].w = (tree[rson].w + 1ll * (tree[rson].r - tree[rson].l + 1) * tree[now].lazy % p) % p;
        tree[now].lazy = 0; return;
    }
    void update(int x, int y, int k, int now) {
        if (tree[now].l >= x && tree[now].r <= y) {
            tree[now].w = (tree[now].w + 1ll * (tree[now].r - tree[now].l + 1) * k % p) % p;
            tree[now].lazy = (tree[now].lazy + k) % p; return;
        }
        if (tree[now].lazy) pushdown(now);
        int mid = (tree[now].l + tree[now].r) >> 1;
        if (x <= mid) update(x, y, k, lson);
        if (y > mid) update(x, y, k, rson);
        tree[now].w = (tree[lson].w + tree[rson].w) % p;
    }
    int query(int x, int y, int now) {
        if (tree[now].l >= x && tree[now].r <= y) return tree[now].w;
        if (tree[now].lazy) pushdown(now);
        int mid = (tree[now].l + tree[now].r) >> 1, ans = 0;
        if (x <= mid) ans = (ans + query(x, y, lson)) % p;
        if (y > mid) ans = (ans + query(x, y, rson)) % p;
        return ans;
    }
}

namespace Cut {
    int pthn, dep[M], head[M];
    int cnt, fa[M], son[M], top[M];
    struct Edge {
        int nxt, to;
    }pth[M << 1];
    void add(int frm, int to) {
        pth[++pthn].to = to, pth[pthn].nxt = head[frm];
        head[frm] = pthn;
    }
    void dfs1(int u, int father) {
        fa[u] = father, dep[u] = dep[father] + 1, size[u] = 1;
        for (int i = head[u]; i; i = pth[i].nxt) {
            int v = pth[i].to;
            if (v != father) {
                dfs1(v, u), size[u] += size[v];
                if (size[v] > size[son[u]]) son[u] = v;
            }
        }
    }
    void dfs2(int u, int tp) {
        dfn[u] = ++cnt, pre[cnt] = u, top[u] = tp;
        if (son[u]) dfs2(son[u], tp);
        for (int i = head[u]; i; i = pth[i].nxt) {
            int v = pth[i].to;
            if (v != fa[u] && v != son[u]) dfs2(v, v);
        }
    }
    void change(int x, int y, int k) {
        while (top[x] != top[y]) {
            if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
            Seg::update(dfn[top[x]], dfn[x], k, 1);
            x = fa[top[x]];
        }
        if (dfn[x] > dfn[y]) std::swap(x, y);
        Seg::update(dfn[x], dfn[y], k, 1); 
    }
    int ask(int x, int y) {
        int ans = 0;
        while (top[x] != top[y]) {
            if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
            ans = (ans + Seg::query(dfn[top[x]], dfn[x], 1)) % p;
            x = fa[top[x]];
        }
        if (dfn[x] > dfn[y]) std::swap(x, y);
        ans = (ans + Seg::query(dfn[x], dfn[y], 1)) % p;
        return ans;
    }
}

int main() {
    read(n), read(m), read(r), read(p);
    for (int i = 1; i <= n; ++i) read(a[i]);
    for (int i = 1, u, v; i < n; ++i) {
        read(u), read(v);
        Cut::add(u, v), Cut::add(v, u);
    }
    Cut::dfs1(r, 0), Cut::dfs2(r, r), Seg::build(1, n, 1);
    for (int i = 1, opt, x, y, k; i <= m; ++i) {
        read(opt), read(x);
        if (opt == 1) { read(y), read(k), Cut::change(x, y, k); }
        if (opt == 2) { read(y), printf("%d
", Cut::ask(x, y)); }
        if (opt == 3) { read(y), Seg::update(dfn[x], dfn[x] + size[x] - 1, y, 1); }
        if (opt == 4) { printf("%d
", Seg::query(dfn[x], dfn[x] + size[x] - 1, 1)); }
    }
    return 0;
}

线段树

// time : 20210103
// test on https://www.luogu.com.cn/problem/P3373

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 100001
#define lson now << 1
#define rson now << 1 | 1

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

int n, m, p;
struct Node {
    int l, r, w, add, mul;
}tree[M << 2];

void build(int l, int r, int now) {
    tree[now].l = l, tree[now].r = r;
    tree[now].add = 0, tree[now].mul = 1;
    if (tree[now].l == tree[now].r) {
        read(tree[now].w); return;
    }
    int mid = (tree[now].l + tree[now].r) >> 1;
    build(l, mid, lson), build(mid + 1, r, rson);
    tree[now].w = (tree[lson].w + tree[rson].w) % p;
}

void pushdown(int now) {
    if (tree[now].l == tree[now].r) return;
    tree[lson].mul = 1ll * tree[lson].mul * tree[now].mul % p;
    tree[rson].mul = 1ll * tree[rson].mul * tree[now].mul % p;
    tree[lson].add = (1ll * tree[lson].add * tree[now].mul % p + tree[now].add) % p;
    tree[rson].add = (1ll * tree[rson].add * tree[now].mul % p + tree[now].add) % p;
    tree[lson].w = (1ll * tree[lson].w * tree[now].mul % p + 1ll * (tree[lson].r - tree[lson].l + 1) * tree[now].add % p) % p;
    tree[rson].w = (1ll * tree[rson].w * tree[now].mul % p + 1ll * (tree[rson].r - tree[rson].l + 1) * tree[now].add % p) % p;
    tree[now].mul = 1, tree[now].add = 0;
}

void update1(int x, int y, int k, int now) {
    if (tree[now].l >= x && tree[now].r <= y) {
        tree[now].w = 1ll * tree[now].w * k % p;
        tree[now].mul = 1ll * tree[now].mul * k % p;
        tree[now].add = 1ll * tree[now].add * k % p;
        return;
    }
    if (tree[now].mul != 1 || tree[now].add) pushdown(now);
    int mid = (tree[now].l + tree[now].r) >> 1;
    if (x <= mid) update1(x, y, k, lson);
    if (y > mid) update1(x, y, k, rson);
    tree[now].w = (tree[lson].w + tree[rson].w) % p;
}

void update2(int x, int y, int k, int now) {
    if (tree[now].l >= x && tree[now].r <= y) {
        tree[now].w = (tree[now].w + 1ll * (tree[now].r - tree[now].l + 1) * k % p) % p;
        tree[now].add = (tree[now].add + k) % p; return;
    }
    if (tree[now].mul != 1 || tree[now].add) pushdown(now);
    int mid = (tree[now].l + tree[now].r) >> 1;
    if (x <= mid) update2(x, y, k, lson);
    if (y > mid) update2(x, y, k, rson);
    tree[now].w = (tree[lson].w + tree[rson].w) % p;
}

int query(int x, int y, int now) {
    if (tree[now].l >= x && tree[now].r <= y) return tree[now].w;
    if (tree[now].mul != 1 || tree[now].add) pushdown(now);
    int mid = (tree[now].l + tree[now].r) >> 1, ans = 0;
    if (x <= mid) ans = (ans + query(x, y, lson)) % p;
    if (y > mid) ans = (ans + query(x, y, rson)) % p;
    return ans;
}

int main() {
    read(n), read(m), read(p);
    build(1, n, 1);
    for (int i = 1, opt, x, y, k; i <= m; ++i) {
        read(opt), read(x), read(y);
        if (opt == 1) { read(k), update1(x, y, k, 1); }
        if (opt == 2) { read(k), update2(x, y, k, 1); }
        if (opt == 3) printf("%d
", query(x, y, 1));
    }
    return 0;
}

树状数组

// time : 20210103
// test on https://www.luogu.com.cn/problem/P3374
// test on https://www.luogu.com.cn/problem/P3368

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 500001
#define lowbit(x) x & (-x)

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

int n, m;
struct Bit {
    int c[M];
    void add(int x, int k) {
        while (x <= n) { c[x] += k, x += lowbit(x); }
    }
    int ask(int x, int ans = 0) {
        while (x > 0) { ans += c[x], x -= lowbit(x); }
        return ans;
    }
}b;

int main() {
    read(n), read(m);
    
    //bit1
    for (int i = 1, x; i <= n; ++i) {
        read(x), b.add(i, x);
    }
    for (int i = 1, opt, x, y; i <= m; ++i) {
        read(opt), read(x), read(y);
        if (opt == 1) b.add(x, y);
        else printf("%d
", b.ask(y) - b.ask(x - 1));
    }
    
    //bit2
    for (int i = 1, last = 0, x; i <= n; ++i, last = x) {
        read(x), b.add(i, x - last);
    }
    for (int i = 1, opt, x, y, k; i <= m; ++i) {
        read(opt), read(x);
        if (opt == 1) {
            read(y), read(k);
            b.add(x, k), b.add(y + 1, -k);
        }
        else printf("%d
", b.ask(x));
    }
    
    return 0;
}

缩点(tarjan)

// time : 20210103
// test on https://www.luogu.com.cn/problem/P3387

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#define M 100001

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

bool vis[M];
std::queue<int> q;
int n, m, ans, a[M], x[M], y[M], f[M], pthn, head[M];
int c, t, sc, b[M], s[M], dfn[M], low[M], num[M], ideg[M];
struct Edge {
    int nxt, to;
}pth[M];

void add(int frm, int to) {
    pth[++pthn].to = to, pth[pthn].nxt = head[frm];
    head[frm] = pthn;
}

void format() {
    memset(head, 0, sizeof head);
    for (int i = 1; i <= pthn; ++i) {
        pth[i].nxt = pth[i].to = 0;
    }
    pthn = 0;
}

void tarjan(int u) {
    low[u] = dfn[u] = ++c;
    vis[u] = true, s[++sc] = u;
    for (int i = head[u]; i; i = pth[i].nxt) {
        int v = pth[i].to;
        if (!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if (vis[v]) low[u] = min(low[u], dfn[v]);
    }
    if (low[u] == dfn[u]) {
        int now = s[sc--]; num[now] = ++t;
        b[t] += a[now], vis[now] = false;
        while (now != u) {
            now = s[sc--], num[now] = t;
            b[t] += a[now], vis[now] = false;
        }
    }
}

int main() {
    read(n), read(m);
    for (int i = 1; i <= n; ++i) read(a[i]);
    for (int i = 1; i <= m; ++i) {
        read(x[i]), read(y[i]);
        add(x[i], y[i]);
    }
    for (int i = 1; i <= n; ++i) {
        if (!dfn[i]) tarjan(i);
    }
    format();
    for (int i = 1; i <= m; ++i) {
        if (num[x[i]] != num[y[i]]) {
            add(num[x[i]], num[y[i]]);
            ++ideg[num[y[i]]];
        }
    }
    for (int i = 1; i <= t; ++i) {
        if (!ideg[i]) q.push(i), f[i] = b[i];
    }
    while (!q.empty()) {
        int u = q.front(); q.pop();
        ans = max(ans, f[u]);
        for (int i = head[u]; i; i = pth[i].nxt) {
            int v = pth[i].to; --ideg[v];
            f[v] = max(f[v], f[u] + b[v]);
            if (!ideg[v]) q.push(v);
        }
    }
    std::cout << ans << '
';
    return 0;
}

回滚莫队(不删除莫队)

// time : 20200103
// test on https://www.luogu.com.cn/problem/P5906

#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 200001

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x; 
}

int n, m, a[M], fir[M], las[M];
int sqrn, num[M], ans[M], fir_[M];
struct query {
    int x, y, id;
    friend bool operator < (query q1, query q2) {
        if (num[q1.x] == num[q2.x]) return q1.y < q2.y;
        else return num[q1.x] < num[q2.x];
    }
}q[M];
struct lsh {
    int w, id;
    friend bool operator < (lsh l1, lsh l2) {
        return l1.w < l2.w;
    }
}b[M];

int main() {
    read(n), sqrn = sqrt(n);
    for (int i = 1; i <= n; ++i) {
        read(a[i]);
        b[i].id = i, b[i].w = a[i];
        num[i] = (i - 1) / sqrn + 1;
    }
    std::sort(b + 1, b + n + 1);
    for (int i = 1, now = 0; i <= n; ++i) {
        if (b[i].w != b[i - 1].w) ++now;
        a[b[i].id] = now;
    }
    read(m);
    for (int i = 1; i <= m; ++i) {
        read(q[i].x), read(q[i].y);
        q[i].id = i;
    }
    std::sort(q + 1, q + m + 1);
    int l = 1, r = 0, now = 0, lasb = 0;
    for (int i = 1; i <= m; ++i) {
        if (num[q[i].x] == num[q[i].y]) {
            int temp = 0;
            for (int j = q[i].x; j <= q[i].y; ++j) {
                if (!fir_[a[j]]) fir_[a[j]] = j;
                else temp = max(temp, j - fir_[a[j]]);
            }
            for (int j = q[i].x; j <= q[i].y; ++j) fir_[a[j]] = 0;
            ans[q[i].id] = temp; continue;
        }
        if (lasb != num[q[i].x]) {
            int stop = min(num[q[i].x] * sqrn, n );
            memset(fir, 0, sizeof fir), memset(las, 0, sizeof las);
            l = stop + 1, r = stop, now = 0, lasb = num[q[i].x];
        }
        while (r < q[i].y) {
            ++r;
            if (!fir[a[r]]) fir[a[r]] = las[a[r]] = r;
            else {
                las[a[r]] = r;
                now = max(now, r - fir[a[r]]);
            }
        }
        int l_ = l, temp = now;
        while (l_ > q[i].x) {
            --l_;
            if (!las[a[l_]] && !fir[a[l_]]) las[a[l_]] = l_;
            else temp = max(temp, las[a[l_]] - l_);
        }
        ans[q[i].id] = temp;
        while (l_ < l) {
            if (!fir[a[l_]]) las[a[l_]] = 0;
            ++l_;
        }
    }
    for (int i = 1; i <= m; ++i) printf("%d
", ans[i]);
    return 0;
}

单调栈

// time : 20200103
// test on https://www.luogu.com.cn/problem/P5788

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <stack>
#define M 3000001

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

std::stack<int> s;
int n, a[M], ans[M];

int main() {
    read(n);
    for (int i = 1; i <= n; ++i) read(a[i]);
    for (int i = 1; i <= n; ++i) {
        while (!s.empty() && a[s.top()] < a[i]) {
            ans[s.top()] = i; s.pop();
        }
        s.push(i);
    }
    for (int i = 1; i <= n; ++i) printf("%d ", ans[i]);
    return 0;
}

单调队列

// time : 20200103
// test on https://www.luogu.com.cn/problem/P1886

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#define M 1000001

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

std::deque<int> q1, q2;
int n, k, a[M], min[M], max[M];

int main() {
    read(n), read(k);
    for (int i = 1; i <= n; ++i) read(a[i]);
    for (int i = 1; i <= n; ++i) {
        while (!q1.empty() && q1.front() < i - k + 1) q1.pop_front();
        while (!q2.empty() && q2.front() < i - k + 1) q2.pop_front();
        while (!q1.empty() && a[q1.back()] >= a[i]) q1.pop_back();
        while (!q2.empty() && a[q2.back()] <= a[i]) q2.pop_back();
        q1.push_back(i), q2.push_back(i);
        min[i] = a[q1.front()], max[i] = a[q2.front()];
    }
    for (int i = k; i <= n; ++i) printf("%d ", min[i]);
    puts("");
    for (int i = k; i <= n; ++i) printf("%d ", max[i]);
    return 0;
}

Trie

// time : 20210109
// test on https://www.luogu.com.cn/problem/P2580

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 500001

int n, m;
std::string s;
struct Trie {
    int ender[M];
    int cnt, node[M][27];
    void clear() {
        cnt = 0;
        memset(node, 0, sizeof node);
        memset(ender, 0, sizeof ender);
    }
    void ins() {
        int len = s.length(), now = 0;
        for (int i = 0; i < len; ++i) {
            if (!node[now][s[i] - 'a']) node[now][s[i] - 'a'] = ++cnt;
            now = node[now][s[i] - 'a'];
        }
        ender[now] = true;
    }
    void find() {
        int len = s.length(), now = 0;
        for (int i = 0 ; i < len; ++i) {
            if (node[now][s[i] - 'a']) now = node[now][s[i] - 'a'];
            else { puts("WRONG"); return; }
        }
        ++ender[now];
        if (ender[now] > 2) puts("REPEAT");
        else puts("OK");
    }
}t;

int main() {
    scanf("%d", &n); t.clear();
    for (int i = 1; i <= n; ++i) { std::cin >> s; t.ins(); }
    scanf("%d", &m);
    for (int i = 1; i <= m; ++i) { std::cin >> s; t.find(); }
    return 0;
}

倍增求LCA

// time : 20210110
// test on https://www.luogu.com.cn/problem/P3379

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 500001

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

int n, m, s, pthn, head[M];
int lg[M], dep[M], fa[M][21];
struct Edge {
    int nxt, to;
}pth[M << 1];

void add(int frm, int to) {
    pth[++pthn].to = to, pth[pthn].nxt = head[frm];
    head[frm] = pthn;
}

void dfs(int u, int father) {
    fa[u][0] = father, dep[u] = dep[father] + 1;
    for (int i = head[u]; i; i = pth[i].nxt) {
        int x = pth[i].to;
        if (x != father) dfs(x, u);
    }
}

int lca(int x, int y) {
    if (dep[x] < dep[y]) std::swap(x, y);
    while (dep[x] > dep[y]) {
        x = fa[x][lg[dep[x] - dep[y]] - 1];
    }
    if (x == y) return x;
    for (int k = lg[dep[x]] - 1; k >= 0; --k) {
        if (fa[x][k] != fa[y][k]) {
            x = fa[x][k];
            y = fa[y][k];
        }
    }
    return fa[x][0];
}

int main() {
    read(n), read(m), read(s);
    for (int i = 1, u, v; i < n; ++i) {
        read(u), read(v);
        add(u, v), add(v, u);
    }
    for (int i = 1; i <= n; ++i) {
        lg[i] = lg[i - 1] + ((1 << lg[i - 1]) == i);
    }
    dfs(s, 0);
    for (int j = 1; (1 << j) <= n; ++j) {
        for (int i = 1; i <= n; ++i) {
            fa[i][j] = fa[fa[i][j - 1]][j - 1];
        }
    }
    for (int i = 1, x, y; i <= m; ++i) {
        read(x), read(y);
        printf("%d
", lca(x, y));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/poi-bolg-poi/p/14225023.html