模板

作者: xht37 分类: 记录 发布时间: 2019-08-05 21:46

Visits: 1701

模板汇总,不定期更新

基本模板

IO 优化

//Author:xht37
#include <bits/stdc++.h>

#define ui unsigned int
#define ll long long
#define ul unsigned ll
#define ld long double

#define pi pair <int, int>
#define fi first
#define se second
#define mp make_pair

#define ls (p << 1)
#define rs (ls | 1)
#define md ((t[p].l + t[p].r) >> 1)

#define vi vector <int>
#define pb push_back
#define pq priority_queue

#define dbg(x) cerr << #x" = " << (x) << endl
#define debug(...) fprintf(stderr, __VA_ARGS__)

#define fl(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)

using namespace std;

namespace io {
    const int SI = 1 << 21 | 1;
    char IB[SI], *IS, *IT, OB[SI], *OS = OB, *OT = OS + SI - 1, c, ch[100];
    int f, t;
    #define gc() (IS == IT ? (IT = (IS = IB) + fread(IB, 1, SI, stdin), IS == IT ? EOF : *IS++) : *IS++)
    inline void flush() {
        fwrite(OB, 1, OS - OB, stdout), OS = OB;
    }
    inline void pc(char x) {
        *OS++ = x;
        if (OS == OT) flush();
    }

    template <class I>
    inline void rd(I &x) {
        for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
        for (x = 0; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + (c & 15), c = gc());
        x *= f;
    }
    template <class I>
    inline void rd(I &x, I &y) {
        rd(x), rd(y);
    }
    template <class I>
    inline void rd(I &x, I &y, I &z) {
        rd(x), rd(y), rd(z);
    }
    template <class I>
    inline void rda(I *a, int n) {
        for (int i = 1; i <= n; i++) rd(a[i]);
    }
    inline void rdc(char &c) {
        for (c = gc(); c < 33 || c > 126; c = gc());
    }
    inline void rds(char *s, int &n) {
        for (c = gc(); c < 33 || c > 126; c = gc());
        for (n = 0; c >= 33 && c <= 126; s[++n] = c, c = gc());
    }
    inline void rds(string &s) {
        for (c = gc(); c < 33 || c > 126; c = gc());
        for (s.clear(); c >= 33 && c <= 126; s.pb(c), c = gc());
    }

    template <class I>
    inline void print(I x, char k = '\n') {
        if (!x) pc('0');
        if (x < 0) pc('-'), x = -x;
        while (x) ch[++t] = x % 10 + '0', x /= 10;
        while (t) pc(ch[t--]);
        pc(k);
    }
    template <class I>
    inline void print(I x, I y) {
        print(x, ' '), print(y);
    }
    template <class I>
    inline void print(I x, I y, I z) {
        print(x, ' '), print(y, ' '), print(z);
    }
    template <class I>
    inline void printa(I *a, int n) {
        for (int i = 1; i <= n; i++) print(a[i], " \n"[i==n]);
    }
    inline void printc(char c) {
        pc(c);
    }
    inline void prints(char *s, int n) {
        for (int i = 1; i <= n; i++) pc(s[i]);
        pc('\n');
    }
    inline void prints(string s) {
        int n = s.length();
        while (t < n) pc(s[t++]);
        pc('\n'), t = 0;
    }
    struct Flush {
        ~Flush() {
            flush();
        }
    } flusher;
}
using io::rd;
using io::rda;
using io::rdc;
using io::rds;
using io::print;
using io::printa;
using io::printc;
using io::prints;

int main() {

    return 0;
}

模运算

const int P = P;

struct modint {
    int x;
    inline modint(int x = 0) : x(x) {}
    inline modint &operator = (int o) { return x = o, *this; }
    inline modint &operator += (modint o) { return (x += o.x) >= P && (x -= P), *this; }
    inline modint &operator -= (modint o) { return (x -= o.x) < 0 && (x += P), *this; }
    inline modint &operator *= (modint o) { return x = 1ll * x * o.x % P, *this; }
    template <class I>
    inline modint &operator ^= (I b) {
        modint a = *this, c;
        if (!~b) b = P - 2;
        c.x = 1 % P;
        while (b) {
            if (b & 1) c *= a;
            a *= a, b >>= 1;
        }
        return x = c.x, *this;
    }
    inline modint &operator /= (modint o) { return *this *= o ^ -1; }
    inline modint &operator += (int o) { return (x += o) >= P && (x -= P), *this; }
    inline modint &operator -= (int o) { return (x -= o) < 0 && (x += P), *this; }
    inline modint &operator *= (int o) { return x = 1ll * x * o % P, *this; }
    inline modint &operator /= (int o) { return *this *= (modint)o ^ -1; }
    template <class I>
    inline friend modint operator + (modint a, I b) { return a += b; }
    template <class I>
    inline friend modint operator - (modint a, I b) { return a -= b; }
    template <class I>
    inline friend modint operator * (modint a, I b) { return a *= b; }
    template <class I>
    inline friend modint operator ^ (modint a, I b) { return a ^= b; }
    template <class I>
    inline friend modint operator / (modint a, I b) { return a /= b; }
    inline friend bool operator == (modint a, int b) { return a.x == b; }
    inline friend bool operator != (modint a, int b) { return a.x != b; }
    inline friend bool operator < (modint a, int b) { return a.x < b; }
    inline friend bool operator <= (modint a, int b) { return a.x <= b; }
    inline friend bool operator > (modint a, int b) { return a.x > b; }
    inline friend bool operator >= (modint a, int b) { return a.x >= b; }
    inline friend bool operator == (modint a, modint b) { return a.x == b.x; }
    inline friend bool operator != (modint a, modint b) { return a.x != b.x; }
    inline friend bool operator < (modint a, modint b) { return a.x < b.x; }
    inline friend bool operator <= (modint a, modint b) { return a.x <= b.x; }
    inline friend bool operator > (modint a, modint b) { return a.x > b.x; }
    inline friend bool operator >= (modint a, modint b) { return a.x >= b.x; }
    inline bool operator ! () { return !x; }
    inline modint operator - () { return x ? P - x : 0; }
};
inline void rd(modint &x) { rd(x.x); }
inline void print(modint x, char k = '\n') { print(x.x, k); }

//const int NP = 1e6 + 7;
//modint p[NP], v[NP], vp[NP];
//inline void init(int n) {
//  p[0] = v[0] = 1;
//  for (int i = 1; i <= n; i++) p[i] = p[i-1] * i;
//  vp[n] = 1 / p[n];
//  for (int i = n; i; i--) v[i] = vp[i] * p[i-1], vp[i-1] = vp[i] * i;
//}
//inline modint binom(int n, int m) {
//  return (m < 0 || n < m) ? 0 : p[n] * vp[m] * vp[n-m];
//}

随机数

namespace Rd {
    inline bool gt() {
        int a = rand(), b = rand();
        while (a == b) a = rand(), b = rand();
        return a < b;
    }
    template <class I>
    inline I rd(I k) {
        I w = 1;
        while (w < k) w <<= 1;
        while (w >= k) {
            I o = 1, x = 0;
            while (o < k) o <<= 1, x = x << 1 | gt();
            w = x;
        }
        return w;
    }
    template <class I>
    inline I rdm(I l, I r) {
        return l == r ? l : l + rd(r - l + 1);
    }
    template <class I>
    inline void rdms(I *a, int n) {
        for (int i = n; i; i--) swap(a[i], a[rdm(1,i)]);
    }
}
using Rd::rdm;
using Rd::rdms;

int main() {
//  freopen("1.in", "w", stdout);

    int seed;
    rd(seed);
    srand(seed ^ time(0));


    return 0;
}

对拍模板

Windows

#include <bits/stdc++.h>

using namespace std;

const int T = 1e5;
const string cpp = "1", io = "1";

int main() {
    for (int i = 1; i <= T; i++) {
        FILE *fp = fopen("tmp.in", "w");
        fprintf(fp, "%d\n", i);
        fclose(fp);
        system(("rd.exe < tmp.in > " + io + ".in").c_str());
        double l = clock();
        system((cpp + ".exe < " + io + ".in > " + io + ".out").c_str());
        double r = clock();
        system(("bl.exe < " + io + ".in > " + io + ".ans").c_str());
        if (system(("fc " + io + ".out " + io + ".ans").c_str()))
            return puts("WA"), 0;
        else printf("%d AC %.3fs\n\n\n", i, (r - l) / CLOCKS_PER_SEC);
    }
    return 0;
}

Linux

#include <bits/stdc++.h>

using namespace std;

const int T = 1e5;

int main() {
    for (int i = 1; i <= T; i++) {
        system("./rd");
        double l = clock();
        system("./1");
        double r = clock();
        system("./bl");
        if (system("diff 1.out 1.ans")) return puts("WA"), 0;
        else printf("%d AC %.3fs\n", i, (r - l) / CLOCKS_PER_SEC);
    }
    return 0;
}

动态规划模板

矩阵加速

struct mat {
    modint a[N][N];
    inline friend mat operator * (const mat &x, const mat &y) {
        mat z;
        for (int i = 0; i < N; i++)
            for (int k = 0; k < N; k++)
                for (int j = 0; j < N; j++)
                    z.a[i][j] += x.a[i][k] * y.a[k][j];
        return z;
    }
    inline friend mat operator ^ (mat x, ll y) {
        mat z;
        for (int i = 0; i < N; i++) z.a[i][i] = 1;
        while (y) {
            if (y & 1) z = z * x;
            x = x * x, y >>= 1;
        }
        return z;
    }
};

字符串模板

KMP

const int N = 1e6 + 7;
int n, m, p[N], ans;
char a[N], b[N];

int main() {
    rds(a, n), rds(b, m);
    for (int i = 2, j = 0; i <= m; i++) {
        while (j && b[i] != b[j+1]) j = p[j];
        if (b[i] == b[j+1]) ++j;
        p[i] = j;
    }
    for (int i = 1, j = 0; i <= n; i++) {
        while (j && a[i] != b[j+1]) j = p[j];
        if (a[i] == b[j+1]) ++j;
        ans += j == m;
    }
    print(ans);
    return 0;
}

AC 自动机

struct AC {
    int trie[N][27], fail[N], t = 1;

    inline int ins(char *s, int n) {
        int p = 1;
        for (int i = 1; i <= n; i++) {
            int c = s[i] - 'a';
            if (!trie[p][c]) trie[p][c] = ++t;
            p = trie[p][c];
        }
        return p;
    }

    inline void main() {
        queue<int> q;
        for (int i = 0; i < 26; i++)
            if (trie[1][i]) fail[trie[1][i]] = 1, q.push(trie[1][i]);
            else trie[1][i] = 1;
        while (q.size()) {
            int x = q.front();
            q.pop();
            for (int i = 0; i < 26; i++)
                if (trie[x][i]) fail[trie[x][i]] = trie[fail[x]][i], q.push(trie[x][i]);
                else trie[x][i] = trie[fail[x]][i];
        }
    }

    inline int get(char *s, int n) {
        int p = 1;
        for (int i = 1; i <= n; i++) {
            int c = s[i] - 'a';
            p = trie[p][c];
        }
        return p;
    }
} ac;

SA

int n;
char s[N];

struct SA {
    int m, sa[N], rk[N<<1|1], tp[N<<1|1], tx[N], he[N];
    inline void sort() {
        for (int i = 1; i <= m; i++) tx[i] = 0;
        for (int i = 1; i <= n; i++) ++tx[rk[i]];
        for (int i = 1; i <= m; i++) tx[i] += tx[i-1];
        for (int i = n; i; i--) sa[tx[rk[tp[i]]]--] = tp[i];
    }
    inline bool pd(int i, int j, int k) {
        return tp[i] == tp[j] && tp[i+k] == tp[j+k];
    }
    inline void main() {
        m = 127;
        for (int i = 1; i <= n; i++) rk[i] = s[i], tp[i] = i;
        sort();
        for (int k = 1, p = 0; p < n; k <<= 1, m = p) {
            p = 0;
            for (int i = 1; i <= k; i++) tp[++p] = n - k + i;
            for (int i = 1; i <= n; i++)
                if (sa[i] > k) tp[++p] = sa[i] - k;
            sort(), swap(rk, tp), rk[sa[1]] = p = 1;
            for (int i = 2; i <= n; i++)
                rk[sa[i]] = p += !pd(sa[i], sa[i-1], k);
        }
    }
    inline void height() {
        for (int i = 1, p = 0; i <= n; i++) {
            if (p) --p;
            int j = sa[rk[i]-1];
            while (s[i+p] == s[j+p]) ++p;
            he[rk[i]] = p;
        }
    }
} sa;

数组版 SAM

struct SAM {
    int l, ch[N<<1|1][26], len[N<<1|1], pa[N<<1|1], t;
    inline void add(int c) {
        int w = ++t, p = l;
        len[w] = len[l] + 1;
        while (~p && !ch[p][c]) ch[p][c] = w, p = pa[p];
        if (!~p) return pa[l=w] = 0, void();
        int q = ch[p][c];
        if (len[p] + 1 == len[q]) return pa[l=w] = q, void();
        int k = ++t;
        pa[k] = pa[q], memcpy(ch[k], ch[q], sizeof(ch[k]));
        len[k] = len[p] + 1, pa[w] = pa[q] = k;
        while (~p && ch[p][c] == q) ch[p][c] = k, p = pa[p];
        l = w;
    }
    inline void build() {
        pa[0] = -1;
        for (int i = 1; i <= n; i++) add(s[i] - 'a');
    }

    int b[N<<1], c[N];
    inline void sort() {
        for (int i = 1; i <= n; i++) c[i] = 0;
        for (int i = 1; i <= t; i++) ++c[len[i]];
        for (int i = 1; i <= n; i++) c[i] += c[i-1];
        for (int i = 1; i <= t; i++) b[c[len[i]]--] = i;
    }
} sam;

map 版 SAM

struct SAM {
    int l, len[N<<1|1], pa[N<<1|1], t;
    map<char, int> ch[N<<1|1];
    inline void add(char c) {
        int w = ++t, p = l;
        len[w] = len[l] + 1;
        while (~p && !ch[p][c]) ch[p][c] = w, p = pa[p];
        if (!~p) return pa[l=w] = 0, void();
        int q = ch[p][c];
        if (len[p] + 1 == len[q]) return pa[l=w] = q, void();
        int k = ++t;
        pa[k] = pa[q], ch[k] = ch[q];
        len[k] = len[p] + 1, pa[w] = pa[q] = k;
        while (~p && ch[p][c] == q) ch[p][c] = k, p = pa[p];
        l = w;
    }
    inline void build() {
        pa[0] = -1;
        for (int i = 1; i <= n; i++) add(s[i]);
    }

    int b[N<<1|1], c[N];
    inline void sort() {
        for (int i = 1; i <= n; i++) c[i] = 0;
        for (int i = 1; i <= t; i++) ++c[len[i]];
        for (int i = 1; i <= n; i++) c[i] += c[i-1];
        for (int i = 1; i <= t; i++) b[c[len[i]]--] = i;
    }
} sam;

数论模板

分解质因数

inline vector<pair<ll, int>> divide(ll n) {
    vector<pair<ll, int>> p;
    for (ll i = 2; i * i <= n; i++)
        if (!(n % i)) {
            p.pb(mp(i, 0));
            while (!(n % i)) ++p.back().se, n /= i;
        }
    if (n > 1) p.pb(mp(n, 1));
    return p;
}

线性筛

namespace shai {
    const int N = 1e6 + 7;
    int p[N], v[N], phi[N], miu[N];

    inline void init(int n) {
        v[1] = phi[1] = miu[1] = 1;
        for (int i = 2; i <= n; i++) {
            if (!v[i]) p[++p[0]] = v[i] = i, phi[i] = i - 1, miu[i] = -1;
            for (int j = 1; j <= p[0] && i * p[j] <= n && p[j] <= v[i]; j++)
                v[i*p[j]] = p[j],
                phi[i*p[j]] = phi[i] * (p[j] - 1 + (p[j] == v[i])),
                miu[i*p[j]] = p[j] == v[i] ? 0 : -miu[i];
        }
    }
}

线性基

inline bool ins(int x) {
    for (int i = n - 1; ~i; i--)
        if (x >> i & 1) {
            if (!b[i]) return b[i] = x, 1;
            x ^= b[i];
        }
    return 0;
}

多项式模板

拉格朗日插值

const int N = 2e3 + 7;
int n;
modint k, x[N], y[N], ans;

int main() {
    rd(n), rd(k);
    for (int i = 1; i <= n; i++) rd(x[i]), rd(y[i]);
    for (int i = 1; i <= n; i++) {
        modint a = y[i], b = 1;
        for (int j = 1; j <= n; j++)
            if (i != j) a *= k - x[j], b *= x[i] - x[j];
        ans += a / b;
    }
    print(ans);
    return 0;
}

FFT

namespace FFT {
    const int N = 1 << 21 | 1;
    const double PI = acos(-1);
    struct I {
        double x, y;
        inline I() {}
        inline I(double x, double y) : x(x), y(y) {}
        inline I &operator = (int o) { return x = o, y = 0, *this; }
        inline I operator + (const I o) const { return I(x + o.x, y + o.y); }
        inline I operator - (const I o) const { return I(x - o.x, y - o.y); }
        inline I operator * (const I o) const {
            return I(x * o.x - y * o.y, x * o.y + y * o.x);
        }
    } a[N], b[N];
    inline void rd(I &x) { int o; ::rd(o), x = o; }
    inline void print(I x, char k = '\n') { ::print((int)(x.x + 0.5), k); }
    int n, m, k, l, r[N];
    inline void fft(I *a, int n, int x) {
        for (int i = 0; i < n; i++) if (i < r[i]) swap(a[i], a[r[i]]);
        for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1) {
            I W = I(cos(PI / k), x * sin(PI / k));
            for (int i = 0; i < n; i += o) {
                I w = I(1, 0);
                for (int j = 0; j < k; j++, w = w * W) {
                    I x = a[i+j], y = w * a[i+j+k];
                    a[i+j] = x + y, a[i+j+k] = x - y;
                }
            }
        }
    }
    inline void solve() {
        k = 1, l = 0;
        while (k <= n + m) k <<= 1, ++l;
        for (int i = 0; i < k; i++)
            r[i] = (r[i>>1] >> 1) | ((i & 1) << (l - 1));
        for (int i = n + 1; i < k; i++) a[i] = 0;
        for (int i = m + 1; i < k; i++) b[i] = 0;
        fft(a, k, 1), fft(b, k, 1);
        for (int i = 0; i < k; i++) a[i] = a[i] * b[i];
        fft(a, k, -1);
        for (int i = 0; i <= n + m; i++) a[i].x /= k;
    }
}

NTT

namespace NTT {
    const int N = 1 << 21 | 1;
    const modint g = 3, vg = 1 / g;
    int n, m, k, l, r[N];
    modint vk, a[N], b[N];
    inline void ntt(modint *a, int n, modint x) {
        for (int i = 0; i < n; i++)
            if (i < r[i]) swap(a[i], a[r[i]]);
        for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1) {
            modint W = x ^ ((P - 1) / o);
            for (int i = 0; i < n; i += o) {
                modint w = 1;
                for (int j = 0; j < k; j++, w *= W) {
                    modint x = a[i+j], y = a[i+j+k] * w;
                    a[i+j] = x + y, a[i+j+k] = x - y;
                }
            }
        }
    }
    inline void solve() {
        k = 1, l = 0;
        while (k <= n + m) k <<= 1, ++l;
        vk = (modint)1 / k;
        for (int i = 0; i < k; i++)
            r[i] = r[i>>1] >> 1 | (i & 1) << (l - 1);
        for (int i = n + 1; i < k; i++) a[i] = 0;
        for (int i = m + 1; i < k; i++) b[i] = 0;
        ntt(a, k, g), ntt(b, k, g);
        for (int i = 0; i < k; i++) a[i] *= b[i];
        ntt(a, k, vg);
        for (int i = 0; i <= n + m; i++) a[i] *= vk;
    }
}

FWT

int n, m;
modint A[N], B[N], a[N], b[N];

inline void in() {
    for (int i = 0; i < n; i++) a[i] = A[i], b[i] = B[i];
}

inline void get() {
    for (int i = 0; i < n; i++) a[i] *= b[i];
}

inline void out() {
    for (int i = 0; i < n; i++) print(a[i], " \n"[i==n-1]);
}

inline void OR(modint *f, modint x) {
    for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
        for (int i = 0; i < n; i += o)
            for (int j = 0; j < k; j++)
                f[i+j+k] += f[i+j] * x;
}

inline void AND(modint *f, modint x) {
    for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
        for (int i = 0; i < n; i += o)
            for (int j = 0; j < k; j++)
                f[i+j] += f[i+j+k] * x;
}

inline void XOR(modint *f, modint x) {
    for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
        for (int i = 0; i < n; i += o)
            for (int j = 0; j < k; j++) {
                modint p = f[i+j] * x, q = f[i+j+k] * x;
                f[i+j] = p + q, f[i+j+k] = p - q;
            }
}

int main() {
    rd(m), n = 1 << m;
    for (int i = 0; i < n; i++) rd(A[i]);
    for (int i = 0; i < n; i++) rd(B[i]);
    in(), OR(a, 1), OR(b, 1), get(), OR(a, P - 1), out();
    in(), AND(a, 1), AND(b, 1), get(), AND(a, P - 1), out();
    in(), XOR(a, 1), XOR(b, 1), get(), XOR(a, (modint)1 / 2), out();
    return 0;
}

计数模板

Prufer 序列

int n, f[N], p[N], d[N];
ll ans;

inline void TP() {
    for (int i = 1; i < n; i++) rd(f[i]), ++d[f[i]];
    for (int i = 1, j = 1; i <= n - 2; i++, j++) {
        while (d[j]) ++j; p[i] = f[j];
        while (i <= n - 2 && !--d[p[i]] && p[i] < j) p[i+1] = f[p[i]], ++i;
    }
    for (int i = 1; i <= n - 2; i++) ans ^= 1ll * i * p[i];
}

inline void PT() {
    for (int i = 1; i <= n - 2; i++) rd(p[i]), ++d[p[i]]; p[n-1] = n;
    for (int i = 1, j = 1; i < n; i++, j++) {
        while (d[j]) ++j; f[j] = p[i];
        while (i < n && !--d[p[i]] && p[i] < j) f[p[i]] = p[i+1], ++i;
    }
    for (int i = 1; i < n; i++) ans ^= 1ll * i * f[i];
}

数据结构模板

ST 表

int st[2][N][21];

inline void init(int *a, int n) {
    int w = log2(n);
    for (int i = 1; i <= n; i++)
        st[0][i][0] = st[1][i][0] = a[i];
    for (int i = 1; i <= w; i++)
        for (int l = 1, r = 1 << i; r <= n; l++, r++)
            st[0][l][i] = min(st[0][l][i-1], st[0][l+(1<<(i-1))][i-1]),
            st[1][l][i] = max(st[1][l][i-1], st[1][l+(1<<(i-1))][i-1]);
}

inline int Min(int l, int r) {
    int w = log2(r - l + 1);
    return min(st[0][l][w], st[0][r-(1<<w)+1][w]);
}

inline int Max(int l, int r) {
    int w = log2(r - l + 1);
    return max(st[1][l][w], st[1][r-(1<<w)+1][w]);
}

树状数组

struct BIT {
    vector<ll> c;
    inline BIT() {}
    inline BIT(int n) { c.resize(n); }
    inline void add(ui x, ll k) {
        while (x < c.size()) c[x] += k, x += x & -x;
    }
    inline ll ask(ui x) {
        ll k = 0;
        while (x) k += c[x], x -= x & -x;
        return k;
    }
};

线段树

struct SGT {
    struct T {
        int l, r;
        ll x, z;
    } t[N<<2|1];

    inline void update(int p) {
        t[p].x = t[ls].x + t[rs].x;
    }

    inline void work(int p, ll x) {
        t[p].x += x * (t[p].r - t[p].l + 1), t[p].z += x; 
    }

    inline void spread(int p) {
        if (t[p].z) work(ls, t[p].z), work(rs, t[p].z), t[p].z = 0;
    }

    void build(int p, int l, int r) {
        t[p].l = l, t[p].r = r;
        if (l == r) return t[p].x = a[l], void();
        build(ls, l, md), build(rs, md + 1, r);
        update(p);
    }

    void add(int p, int l, int r, ll x) {
        if (t[p].l >= l && t[p].r <= r) return work(p, x);
        spread(p);
        if (l <= md) add(ls, l, r, x);
        if (r > md) add(rs, l, r, x);
        update(p);
    }

    ll ask(int p, int l, int r) {
        if (t[p].l >= l && t[p].r <= r) return t[p].x;
        spread(p);
        ll ret = 0;
        if (l <= md) ret += ask(ls, l, r);
        if (r > md) ret += ask(rs, l, r);
        return ret;
    }
};

树链剖分

namespace HLD {
    int d[N], f[N], s[N], son[N], dfn[N], rnk[N], top[N], num;

    void dfs(int x) {
        s[x] = 1;
        for (int y : e[x])
            if (y != f[x]) {
                f[y] = x, d[y] = d[x] + 1;
                dfs(y), s[x] += s[y];
                if (s[y] > s[son[x]]) son[x] = y;
            }
    }

    void dfs(int x, int p) {
        dfn[x] = ++num, rnk[num] = x;
        top[x] = p;
        if (son[x]) dfs(son[x], p);
        for (int y : e[x])
            if (y != f[x] && y != son[x])
                dfs(y, y);
    }

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

    inline void main() {
        d[1] = 1, dfs(1), dfs(1, 1);
    }
}

LCT

struct LCT {
    int f[N], ch[N][2], s[N], v[N], a[N], c[N];
    #define lc ch[p][0]
    #define rc ch[p][1]
    #define upd(p) s[p] = s[ch[p][0]] + s[ch[p][1]] + 1, c[p] = c[ch[p][0]] ^ c[ch[p][1]] ^ a[p]
    #define get(p) (p == ch[f[p]][1])
    #define rev(p) v[p] ^= 1, swap(ch[p][0], ch[p][1])
    #define isrt(p) (ch[f[p]][0] != p && ch[f[p]][1] != p)
    inline void spd(int p) {
        if (p && v[p]) {
            if (lc) rev(lc);
            if (rc) rev(rc);
            v[p] = 0;
        }
    }
    inline void rot(int p) {
        int x = f[p], y = f[x], u = get(p), v = get(x), o = isrt(x);
        f[ch[p][u^1]] = x, ch[x][u] = ch[p][u^1];
        f[x] = p, ch[p][u^1] = x, upd(x), upd(p);
        if ((f[p] = y) && !o) ch[y][v] = p;
    }
    void pre(int p) {
        if (!isrt(p)) pre(f[p]);
        spd(p);
    }
    inline void splay(int p) {
        pre(p);
        for (int x = f[p]; !isrt(p); rot(p), x = f[p])
            if (!isrt(x)) rot(get(p) == get(x) ? x : p);
    }
    inline void access(int p) {
        for (int x = 0; p; p = f[x=p]) splay(p), rc = x, upd(p);
    }
    inline void mkrt(int p) {
        access(p), splay(p), rev(p);
    }
    inline void split(int x, int y) {
        mkrt(x), access(y), splay(y);
    }
    inline int fdrt(int p) {
        access(p), splay(p);
        while (lc) spd(p), p = lc;
        return splay(p), p;
    }
    inline bool link(int x, int y) {
        mkrt(x);
        return fdrt(y) != x && (f[x] = y);
    }
    inline bool cut(int x, int y) {
        mkrt(x);
        if (fdrt(y) != x || s[x] != 2) return 0;
        return f[y] = ch[x][1] = 0, upd(x), 1;
    }
    inline void chg(int p, int x) {
        mkrt(p), a[p] = x, upd(p);
    }
} lct;

FHQ Treap

struct Treap {
    int rt, tot, ch[N][2], a[N], d[N], s[N];
    #define lc ch[p][0]
    #define rc ch[p][1]
    #define upd(p) s[p] = s[ch[p][0]] + s[ch[p][1]] + 1
    #define clr(p) ch[p][0] = ch[p][1] = a[p] = d[p] = s[p] = 0
    inline void split(int p, int k, int &x, int &y) {
        if (!p) return x = y = 0, void();
        if (a[p] <= k) x = p, split(rc, k, rc, y);
        else y = p, split(lc, k, x, lc);
        upd(p);
    }
    inline int merge(int x, int y) {
        if (!x || !y) return x | y;
        if (d[x] < d[y]) return ch[y][0] = merge(x, ch[y][0]), upd(y), y;
        return ch[x][1] = merge(ch[x][1], y), upd(x), x;
    }
    inline void ins(int k) {
        a[++tot] = k, s[tot] = 1, d[tot] = rand();
        if (!rt) return rt = tot, void();
        int x, y;
        split(rt, k, x, y), rt = merge(merge(x, tot), y);
    }
    inline int rnk(int k) {
        int x, y, ret;
        return split(rt, k - 1, x, y), ret = s[x] + 1, merge(x, y), ret;
    }
    inline int kth(int k) {
        int p = rt;
        while (1)
            if (k <= s[lc]) p = lc;
            else {
                k -= s[lc] + 1;
                if (!k) return a[p];
                p = rc;
            }
    }
    inline int pre(int k) {
        return kth(rnk(k) - 1);
    }
    inline int nxt(int k) {
        return kth(rnk(k + 1));
    }
    inline void del(int k) {
        int x, y, z;
        split(rt, k, x, z), split(x, k - 1, x, y);
        rt = merge(merge(x, merge(ch[y][0], ch[y][1])), z);
        clr(y);
    }
} treap;

普通莫队

int n, m, T, a[N], ans[N], now;
struct Q {
    int l, r, x, y, i;
    inline Q() {}
    inline Q(int l, int r, int i) : l(l), r(r), i(i) { x = l / T, y = r; }
    inline friend bool operator < (const Q &a, const Q &b) {
        return a.x == b.x ? (a.x & 1) ? a.y < b.y : a.y > b.y : a.x < b.x;
    }
} q[N];

inline void work(int x, int k) {

}

int main() {
    rd(n, m), T = n / sqrt(m), rda(a, n);
    for (int i = 1, l, r; i <= m; i++) rd(l, r), q[i] = Q(l, r, i);
    sort(q + 1, q + m + 1);
    for (int i = 1, l = 1, r = 0; i <= m; i++) {
        while (l > q[i].l) work(--l, 1);
        while (r < q[i].r) work(++r, 1);
        while (l < q[i].l) work(l++, -1);
        while (r > q[i].r) work(r--, -1);
        ans[q[i].i] = now;
    }
    for (int i = 1; i <= m; i++) print(ans[i]);
    return 0;
}

带修莫队

int n, m, k, T, a[N], u[N], v[N], ans[N], now;
struct Q {
    int l, r, t, x, y, z, i;
    inline Q() {}
    inline Q(int l, int r, int t, int i) : l(l), r(r), t(t), i(i) { x = l / T, y = r / T, z = t; }
    inline friend bool operator < (const Q &a, const Q &b) {
        return a.x == b.x ? a.y == b.y ? (a.y & 1) ? a.z < b.z : a.z > b.z : (a.x & 1) ? a.y < b.y : a.y > b.y : a.x < b.x;
    }
} q[N];

inline void work(int x, int k) {

}

inline void update(int i, int x) {

}

int main() {
    rd(n, m), T = pow(n, 2.0 / 3.0), rda(a, n);
    for (int i = 1, l, r, t = 0; i <= m; i++) {
        char o;
        rdc(o);
        if (o == 'Q') rd(l, r), ++k, q[k] = Q(l, r, t, k);
        else ++t, rd(u[t], v[t]);
    }
    sort(q + 1, q + k + 1);
    for (int i = 1, l = 1, r = 0, t = 0; i <= k; i++) {
        while (l > q[i].l) work(a[--l], 1);
        while (r < q[i].r) work(a[++r], 1);
        while (l < q[i].l) work(a[l++], -1);
        while (r > q[i].r) work(a[r--], -1);
        while (t < q[i].t) update(i, ++t);
        while (t > q[i].t) update(i, t--);
        ans[q[i].i] = now;
    }
    for (int i = 1; i <= k; i++) print(ans[i]);
    return 0;
}

图论模板

堆优化 Dijkstra 最短路

inline void dij(int S, int *d) {
    for (int i = 1; i <= n; i++) d[i] = inf, v[i] = 0;
    d[S] = 0, q.push(mp(0, S));
    while (q.size()) {
        int x = q.top().se;
        q.pop();
        if (v[x]) continue;
        v[x] = 1;
        for (pi o : e[x]) {
            int y = o.fi, z = o.se;
            if (d[y] > d[x] + z)
                d[y] = d[x] + z, q.push(mp(-d[y], y));
        }
    }
}

Prim 最小生成树

const int inf = 1 << 30;
int n, m, f[N], a[N][N], d[N];
bool v[N];
vi e[N];
ll ans;

inline void prim() {
    for (int i = 0; i <= n; i++) d[i] = inf;
    d[1] = 0;
    for (int i = 1; i <= n; i++) {
        int x = 0;
        for (int j = 1; j <= n; j++)
            if (!v[j] && d[j] < d[x]) x = j;
        v[x] = 1, ans += d[x];
        if (f[x]) e[x].pb(f[x]), e[f[x]].pb(x);
        for (int y = 1; y <= n; y++)
            if (!v[y] && d[y] > a[x][y])
                d[y] = a[x][y], f[y] = x;
    }
}

int main() {
    rd(n, m);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            a[i][j] = inf;
    for (int i = 1; i <= n; i++) a[i][i] = 0;
    for (int i = 1, x, y, z; i <= m; i++)
        rd(x, y, z), a[x][y] = a[y][x] = min(a[x][y], z);
    prim();
    print(ans);
    return 0;
}

虚树

int s[N], t;
vi g[N];

inline vi virtual_tree(vi p) {
    sort(p.begin(), p.end(), [&](int x, int y) { return dfn[x] < dfn[y]; });
    vi q = p;
    for (int x : p) {
        int lca = HLD::lca(x, s[t]);
        if (lca != s[t]) {
            while (t && d[s[t-1]] >= d[lca]) g[s[t-1]].pb(s[t]), --t;
            if (lca != s[t]) g[lca].pb(s[t]), q.pb(s[t] = lca);
        }
        s[++t] = x;
    }
    while (t > 1) g[s[t-1]].pb(s[t]), --t;
    return t = 0, q;
}

匈牙利算法

namespace XYL {
    bool v[N];
    int f[N], ans;

    bool dfs(int x) {
        for (int y : e[x])
            if (!v[y]) {
                v[y] = 1;
                if (!f[y] || dfs(f[y])) return f[y] = x, 1;
            }
        return 0;
    }

    inline void main() {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n + m; j++) v[j] = 0;
            ans += dfs(i);
        }
        for (int i = 1; i <= n + m; i++)
            if (f[i]) f[f[i]] = i;
    }
}

Dinic 最大流

namespace Dinic {
    const int N = 1e5 + 7, M = 2e6 + 7;
    const ll inf = 1e18;
    int n, S, T, d[N];
    int h[N], hi[N], e[M], t[M], tot;
    ll f[M], mxf;

    inline void add(int x, int y, ll z, bool o = 1) {
        e[++tot] = y, f[tot] = z, t[tot] = h[x], h[x] = tot;
        if (o) add(y, x, 0, 0);
    }

    inline bool bfs() {
        for (int i = 1; i <= n; i++) d[i] = 0;
        queue<int> q;
        q.push(S), d[S] = 1;
        while (q.size()) {
            int x = q.front();
            q.pop();
            for (int i = h[x]; i; i = t[i]) {
                int y = e[i];
                ll z = f[i];
                if (d[y] || !z) continue;
                q.push(y), d[y] = d[x] + 1;
                if (y == T) return 1;
            }
        }
        return 0;
    }

    ll dfs(int x, ll now = inf) {
        if (x == T) return now;
        ll rst = now;
        for (int &i = hi[x]; i; i = t[i]) {
            int y = e[i];
            ll z = f[i];
            if (d[y] != d[x] + 1 || !z) continue;
            ll k = dfs(y, min(z, rst));
            if (!k) d[y] = 0;
            else f[i] -= k, f[i^1] += k, rst -= k;
            if (!rst) break;
        }
        return now - rst;
    }

    inline void main() {
        while (bfs()) {
            for (int i = 1; i <= n; i++) hi[i] = h[i];
            ll now;
            while ((now = dfs(S))) mxf += now;
        }
    }

    inline void init(int _n, int _S, int _T) {
        n = _n, S = _S, T = _T, tot = 1, mxf = 0;
        for (int i = 1; i <= n; i++) h[i] = 0; 
    }
}

Dinic 最小费用最大流

namespace Dinic {
    const int N = 1e5 + 7, M = 2e6 + 7;
    const ll inf = 1e18;
    int n, S, T;
    int h[N], hi[N], e[M], t[M], tot;
    ll d[N], f[M], c[M], mxf, ans;
    bool v[N];

    inline void add(int x, int y, ll z, ll w, bool o = 1) {
        e[++tot] = y, f[tot] = z, c[tot] = w, t[tot] = h[x], h[x] = tot;
        if (o) add(y, x, 0, -w, 0);
    }

    inline bool bfs() {
        for (int i = 1; i <= n; i++) d[i] = inf, v[i] = 0;
        queue<int> q;
        q.push(S), d[S] = 0, v[S] = 1;
        while (q.size()) {
            int x = q.front();
            q.pop(), v[x] = 0;
            for (int i = h[x]; i; i = t[i]) {
                int y = e[i];
                ll z = f[i], w = c[i];
                if (d[y] <= d[x] + w || !z) continue;
                d[y] = d[x] + w;
                if (!v[y]) q.push(y), v[y] = 1;
            }
        }
        return d[T] != inf;
    }

    ll dfs(int x, ll now = inf) {
        if (x == T) return now;
        v[x] = 1;
        ll rst = now;
        for (int &i = hi[x]; i; i = t[i]) {
            int y = e[i];
            ll z = f[i], w = c[i];
            if (v[y] || d[y] != d[x] + w || !z) continue;
            ll k = dfs(y, min(z, rst));
            if (!k) d[y] = inf;
            else ans += k * w, f[i] -= k, f[i^1] += k, rst -= k;
            if (!rst) break;
        }
        v[x] = 0;
        return now - rst;
    }

    inline void main() {
        while (bfs()) {
            for (int i = 1; i <= n; i++) hi[i] = h[i];
            ll now;
            while ((now = dfs(S))) mxf += now;
        }
    }

    inline void init(int _n, int _S, int _T) {
        n = _n, S = _S, T = _T, tot = 1, mxf = 0, ans = 0;
        for (int i = 1; i <= n; i++) h[i] = 0; 
    }
}

无源汇上下界可行流

namespace no_ok_flow {
    const int N = 1e5 + 7;
    int n, S, T;
    ll d[N], s;
    inline void add(int x, int y, ll l, ll r) {
        Dinic::add(x, y, r - l), d[y] += l, d[x] -= l;
    }
    inline bool main() {
        for (int i = 1; i <= n; i++)
            if (d[i] > 0) Dinic::add(S, i, d[i]), s += d[i];
            else if (d[i] < 0) Dinic::add(i, T, -d[i]);
        Dinic::main();
        return Dinic::mxf == s;
    }
    inline void init(int _n) {
        n = _n, s = 0, S = n + 1, T = n + 2;
        Dinic::init(n + 2, S, T);
        for (int i = 1; i <= n; i++) d[i] = 0;
    }
}

有源汇上下界最大流

namespace yes_max_flow {
    const ll inf = 1e18;
    int n, S, T;
    inline bool main() {
        no_ok_flow::add(T, S, 0, inf);
        if (!no_ok_flow::main()) return 0;
        Dinic::S = S, Dinic::T = T, Dinic::mxf = 0;
        return Dinic::main(), 1;
    }
    inline void init(int _n, int _S, int _T) {
        n = _n, S = _S, T = _T;
        no_ok_flow::init(n);
    }
}

有源汇上下界最小流

namespace yes_min_flow {
    const ll inf = 1e18;
    int n, S, T;
    inline bool main() {
        no_ok_flow::main();
        no_ok_flow::add(T, S, 0, inf);
        Dinic::main();
        return Dinic::mxf == no_ok_flow::s;
    }
    inline void init(int _n, int _S, int _T) {
        n = _n, S = _S, T = _T;
        no_ok_flow::init(n);
    }
}

无源汇上下界最小费用可行流

namespace no_min_cost_flow {
    const int N = 1e5 + 7;
    int n, S, T;
    ll d[N], s;
    inline void add(int x, int y, ll l, ll r, ll w) {
        Dinic::add(x, y, r - l, w), d[y] += l, d[x] -= l;
    }
    inline bool main() {
        for (int i = 1; i <= n; i++)
            if (d[i] > 0) Dinic::add(S, i, d[i], 0), s += d[i];
            else if (d[i] < 0) Dinic::add(i, T, -d[i], 0);
        Dinic::main();
        return Dinic::mxf == s;
    }
    inline void init(int _n) {
        n = _n, s = 0, S = n + 1, T = n + 2;
        Dinic::init(n + 2, S, T);
        for (int i = 1; i <= n; i++) d[i] = 0;
    }
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注