zoukankan      html  css  js  c++  java
  • 一些需要注意的地方/模板/杂项

    光速乘

    有用到负数用ll,没有则ull

    typedef long long ll;
    
    typedef unsigned long long ull;
    
    ll mul(ll x, ll y, ll Mod) {
        ll res = x * y - (ll)((long double)x / Mod *  y + 0.5L) * Mod;
        return res < 0 ? res + Mod : res;
    }

    斐波那契数列性质

    字符串匹配相关

    AC自动机(二次加强版)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    int n, mat[200010], tr[200010][26], fa[200010], nodeid; 
    
    char s[2000010], t[200010];
    
    int ins(char *str) {
        int u = 0;
        for (int i = 0; str[i]; i++) {
            int c = str[i] - 'a';
            if (!tr[u][c]) tr[u][c] = ++nodeid;
            u = tr[u][c];
        }
        return u;
    }
    
    queue<int> q;
    
    void build() {
        for (int c = 0; c < 26; c++) if (tr[0][c]) q.push(tr[0][c]);
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int c = 0; c < 26; c++)
                if (tr[u][c]) fa[tr[u][c]] = tr[fa[u]][c], q.push(tr[u][c]);
                else tr[u][c] = tr[fa[u]][c];
        }
    }
    
    int head[200010], to[200010], nxt[200010], cnt, sze[200010];
    
    void add_edge(int u, int v) {
        to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
    }
    
    void dfs(int u) {
        for (int i = head[u]; i; i = nxt[i]) dfs(to[i]), sze[u] += sze[to[i]];
    }
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%s", t);
            mat[i] = ins(t);
        }
        build();
        scanf("%s", s);
        for (int i = 0, u = 0; s[i]; i++) sze[u = tr[u][s[i] - 'a']]++;
        for (int i = 1; i <= nodeid; i++) add_edge(fa[i], i);
        dfs(0);
        for (int i = 1; i <= n; i++) printf("%d
    ", sze[mat[i]]);
        return 0;
    }
    View Code

    Z函数(exKMP)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 2e7 + 10;
    
    char a[N], b[N]; int n, m, z[N], p[N]; long long ans;
    
    int main() {
        scanf("%s", a); n = strlen(a);
        scanf("%s", b); m = strlen(b);
        z[0] = 0; int l = 0, r = 0;
        for (int i = 1; i < m; i++) {
            if (i > r) {
                while (i + z[i] < m && b[i + z[i]] == b[z[i]]) z[i]++;
                l = i, r = i + z[i] - 1;
            }
            else {
                z[i] = min(z[i - l], r - i + 1);
                while (i + z[i] < m && b[i + z[i]] == b[z[i]]) z[i]++;
                if (r < i + z[i] - 1) r = i + z[i] - 1, l = i;
            }
        }
        ans = m + 1;
        for (int i = 1; i < m; i++) ans ^= (z[i] + 1ll) * (i + 1ll);
        cout << ans << endl;
        l = r = -1;
        for (int i = 0; i < n; i++) {
            if (i > r) {
                while (i + p[i] < n && p[i] < m && a[i + p[i]] == b[p[i]]) p[i]++;
                l = i, r = i + p[i] - 1;
            }
            else {
                p[i] = min(r - i + 1, z[i - l]);
                while (i + p[i] < n && p[i] < m && a[i + p[i]] == b[p[i]]) p[i]++;
                if (r < i + p[i] - 1) r = i + p[i] - 1, l = i;
            }
        }
        ans = 0;
        for (int i = 0; i < n; i++) ans ^= (p[i] + 1ll) * (i + 1ll);
        cout << ans << endl;
        return 0;
    }
    View Code

    回文相关

    manacher

    #include <bits/stdc++.h>
    using namespace std;
    
    
    int Right = -1, Mid = -1, len[22000010], ans;
    
    char ch, s[22000010];
    
    
    int main() {
        ch = getchar();
        while (ch < 'a' || ch > 'z') ch = getchar();
        int siz = 0;
        for ( ; ; siz++) 
            if (siz & 1) s[siz] = ch, ch = getchar();
            else {
                s[siz] = '#';
                if (ch < 'a' || ch > 'z') break;
            }
        for (int i = 0; i <= siz; i++) {
            len[i] = (Right > i ? min(len[Mid * 2 - i], Right - i) : 1);
            while (0 <= i - len[i] && i + len[i] <= siz && s[i - len[i]] == s[i + len[i]]) len[i]++;
            if (Right < i + len[i]) Right = i + len[i], Mid = i;
            if (ans < len[i]) ans = len[i];
        }
        cout << ans - 1 << endl;
        return 0;
    }
    View Code

    PAM APIO2014.Palindromes

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    int l, las, nodeid, fa[300010], tr[300010][26], len[300010], cnt[300010]; 
    
    char s[300010]; long long ans;
    
    void ins(int c, int n) {
        int cur = las;
        while (s[n - len[cur] - 1] != s[n]) cur = fa[cur];
        int now = tr[cur][c];
        if (!now) {
            now = ++nodeid;
            int v = fa[cur];
            while (s[n - len[v] - 1] != s[n]) v = fa[v];
            fa[now] = tr[v][c];
            tr[cur][c] = now; // 一定要写在下面 
            len[now] = len[cur] + 2;
        }
        cnt[now]++, las = now;
    }
    
    int main() {
        scanf("%s", s + 1); l = strlen(s + 1);
        fa[0] = fa[1] = 1, len[0] = 0, len[1] = -1, nodeid = 1;
        for (int i = 1; i <= l; i++) ins(s[i] - 'a', i);
        for (int i = nodeid; i >= 2; i--) cnt[fa[i]] += cnt[i];
        for (int i = 2; i <= nodeid; i++) ans = max(ans, 1ll * cnt[i] * len[i]);
        cout << ans << endl;
        return 0;
    }
    View Code

    后缀相关

    SA

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 10;
    
    int n, m, tax[N], rak[N << 1], tmp[N << 1], sa[N], num, height[N]; char s[N];
    //注意rak和tmp要开两倍
    
    void rsort() {
        for (int i = 1; i <= m; i++) tax[i] = 0;
        for (int i = 1; i <= n; i++) tax[rak[i]]++;
        for (int i = 1; i <= m; i++) tax[i] += tax[i - 1];
        for (int i = n; i >= 1; i--) sa[tax[rak[tmp[i]]]--] = tmp[i];
    }
    
    void init() {
        for (int i = 1; i <= n; i++) rak[i] = s[i] - '0' + 1, tmp[i] = i;
        m = 75, rsort();
        for (int len = 1, p = 0; p < n; m = p, len <<= 1) {
            num = 0;
            for (int i = n - len + 1; i <= n; i++) tmp[++num] = i;
            for (int i = 1; i <= n; i++) if (sa[i] > len) tmp[++num] = sa[i] - len;
            rsort(), swap(rak, tmp);
            rak[sa[1]] = p = 1;
            for (int i = 2; i <= n; i++) rak[sa[i]] = (tmp[sa[i]] == tmp[sa[i - 1]] && tmp[sa[i] + len] == tmp[sa[i - 1] + len] ? p : ++p);
        }
        int l = 0;
        for (int i = 1; i <= n; i++) {
            if (l) l--;
            int j = sa[rak[i] - 1];
            while (s[i + l] == s[j + l]) l++;
            height[rak[i]] = l;
        }
    } 
    
    int main() {
        scanf("%s", s + 1); n = strlen(s + 1);
        init();
        for (int i = 1; i <= n; i++) printf("%d ", sa[i]);
        return 0;
    }
    View Code

    SAM

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int L = 1e6 + 10, N = 2e6 + 10;
    
    int n, tax[L], ord[N], cnt[N], fa[N], tr[N][26], len[N], nodeid = 1, las = 1;
    
    char s[L];
    
    void ins(int c) {
        int p = las, np = ++nodeid;
        len[np] = len[p] + 1, cnt[np] = 1;
        for ( ; p && !tr[p][c]; p = fa[p]) tr[p][c] = np;
        if (!p) fa[np] = 1;
        else {
            int q = tr[p][c];
            if (len[q] == len[p] + 1) fa[np] = q;
            else {
                int nq = ++nodeid; len[nq] = len[p] + 1;
                for (int k = 0; k < 26; k++) tr[nq][k] = tr[q][k];
                fa[nq] = fa[q], fa[q] = fa[np] = nq;
                for ( ; p && tr[p][c] == q; p = fa[p]) tr[p][c] = nq;
            }
        }
        las = np;
    }
    
    int main() {
        scanf("%s", s + 1); n = strlen(s + 1);
        for (int i = 1; i <= n; i++) ins(s[i] - 'a');
        for (int i = 1; i <= nodeid; i++) tax[len[i]]++;
        for (int i = 1; i <= n; i++) tax[i] += tax[i - 1];
        for (int i = 1; i <= nodeid; i++) ord[tax[len[i]]--] = i;
        long long ans = 0;
        for (int i = nodeid; i; i--) {
            int now = ord[i]; cnt[fa[now]] += cnt[now];
            if (cnt[now] > 1) ans = max(ans, 1ll * cnt[now] * len[now]);
        }
        cout << ans << endl;
        return 0;
    }
    View Code

    广义SAM(在线)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int L = 1e6 + 10, N = 2e6 + 10;
    
    int n, fa[N], trans[N][26], len[N], nodeid = 1, las = 1; char s[L]; long long ans;
    
    void ins(int c) {
        int p = las;
        if (trans[p][c]) {
            int q = trans[p][c];
            if (len[q] == len[p] + 1) las = q;
            else {
                int nq = ++nodeid; len[nq] = len[p] + 1;
                for (int k = 0; k < 26; k++) trans[nq][k] = trans[q][k];
                fa[nq] = fa[q], fa[q] = nq;
                for ( ; p && trans[p][c] == q; p = fa[p]) trans[p][c] = nq;
                las = nq; 
            }
            return ;
        }
        int np = ++nodeid;
        len[np] = len[p] + 1;
        for ( ; p && !trans[p][c]; p = fa[p]) trans[p][c] = np;
        if (!p) fa[np] = 1;
        else {
            int q = trans[p][c];
            if (len[q] == len[p] + 1) fa[np] = q;
            else {
                int nq = ++nodeid; len[nq] = len[p] + 1;
                for (int k = 0; k < 26; k++) trans[nq][k] = trans[q][k];
                fa[nq] = fa[q], fa[q] = fa[np] = nq;
                for ( ; p && trans[p][c] == q; p = fa[p]) trans[p][c] = nq;
            }
        }
        las = np;
    }
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%s", s); las = 1;
            for (int j = 0; s[j]; j++) ins(s[j] - 'a');
        }
        for (int i = 2; i <= nodeid; i++) ans += len[i] - len[fa[i]];
        cout << ans << endl;
        return 0;
    }
    View Code

    广义SAM(离线)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 10;
    
    int n, tr[N][26], f[N], ch[N], pos[N], cnt = 1;
    
    int trans[N << 1][26], fa[N << 1], len[N << 1], nodeid = 1; 
    
    char s[N]; long long ans;
    
    void ins(char *str) {
        int u = 1;
        for (int i = 0; str[i]; i++) {
            int c = str[i] - 'a';
            if (!tr[u][c]) tr[u][c] = ++cnt, f[cnt] = u, ch[cnt] = c;
            u = tr[u][c];
        }
    }
    
    queue<int> q;
    
    int ins(int c, int las) {
        int p = las, np = ++nodeid;
        len[np] = len[p] + 1;
        for ( ; p && !trans[p][c]; p = fa[p]) trans[p][c] = np;
        if (!p) fa[np] = 1;
        else {
            int q = trans[p][c];
            if (len[q] == len[p] + 1) fa[np] = q;
            else {
                int nq = ++nodeid; len[nq] = len[p] + 1;
                for (int k = 0; k < 26; k++) trans[nq][k] = trans[q][k];
                fa[nq] = fa[q], fa[np] = fa[q] = nq;
                for ( ; p && trans[p][c] == q; p = fa[p]) trans[p][c] = nq; 
            }
        }
        return np;
    }
    
    void build() {
        for (int c = 0; c < 26; c++) if (tr[1][c]) q.push(tr[1][c]);
        pos[1] = 1;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            pos[u] = ins(ch[u], pos[f[u]]);
            for (int c = 0; c < 26; c++) if (tr[u][c]) q.push(tr[u][c]);
        }
    }
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%s", s), ins(s);
        build();
        for (int i = 2; i <= nodeid; i++) ans += len[i] - len[fa[i]];
        cout << ans << endl;
        return 0;
    }
    View Code

    最小表示法

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    }
    
    inline void write(int x, char ch) {
        if (x < 0) putchar('-'), x = -x;
        if (x == 0) putchar('0');
        else {
            int num = 0; char cc[22];
            while (x) cc[++num] = x % 10 + 48, x /= 10;
            while (num) putchar(cc[num--]);
        }
        putchar(ch);
    }
    
    
    int n, arr[600010];
    
    
    int main() {
        n = read();
        for (int i = 1; i <= n; i++) arr[i] = arr[i + n] = read();
        int u = 1, v = 2, w = 0;
        while (u <= n && v <= n && w < n) 
            if (arr[u + w] == arr[v + w]) w++;
            else {
                if (arr[u + w] < arr[v + w]) v += w + 1;
                else u += w + 1;
                if (u == v) v++;
                w = 0;
            }
        if (u > v) swap(u, v);
        for (int i = u; i < u + n; i++) write(arr[i], ' ');
        return 0; 
    }
    View Code

    LCT

    #include <bits/stdc++.h>
    
    #define check(x) (tr[fa[x]][1] == x)
    #define isroot(x) (tr[fa[x]][0] != x && tr[fa[x]][1] != x)
    #define pushup(x) (sum[x] = sum[tr[x][0]] ^ sum[tr[x][1]] ^ val[x])
    
    using namespace std;
    
    
    inline int read() {
        int out = 0;
        bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    }
    
    inline void write(int x) {
        if (x < 0) putchar('-'), x = -x;
        if (x == 0) putchar('0');
        else {
            int num = 0;
            char cc[20];
            while (x) cc[++num] = x % 10 + 48, x /= 10;
            while (num) putchar(cc[num--]);
        }
        putchar('
    ');
    }
    
    
    int n, m, val[100010], tr[100010][2], sum[100010], fa[100010];
    
    bool rev[100010];
    
    void rotate(int x) {
        int y = fa[x], z = fa[y], opt1 = check(x), opt2 = check(y);
        if (!isroot(y)) tr[z][opt2] = x; fa[x] = z;
        tr[y][opt1] = tr[x][opt1 ^ 1], fa[tr[x][opt1 ^ 1]] = y;
        tr[x][opt1 ^ 1] = y, fa[y] = x;
        pushup(y), pushup(x);
    }
    
    inline void reverse(int x) {
        swap(tr[x][0], tr[x][1]), rev[x] ^= 1;
    }
    
    inline void pushdown(int x) {
        if (rev[x]) {
            if (tr[x][0]) reverse(tr[x][0]);
            if (tr[x][1]) reverse(tr[x][1]);
            rev[x] = 0;
        }
    }
    
    void pushall(int x) {
        if (!isroot(x)) pushall(fa[x]);
        pushdown(x);
    }
    
    void splay(int x) {
        pushall(x);
        while (!isroot(x)) {
            int y = fa[x], z = fa[y];
            if (!isroot(y)) rotate(check(x) == check(y) ? y : x);
            rotate(x);
        }
        pushup(x);
    }
    
    inline void access(int x) {
        for (int y = 0; x; y = x, x = fa[x]) splay(x), tr[x][1] = y, pushup(x);
    }
    
    inline int findrt(int x) {
        access(x), splay(x);
        while (tr[x][0]) pushdown(x), x = tr[x][0];
        return splay(x), x;
    }
    
    inline void makert(int x) {
        access(x), splay(x), reverse(x);
    }
    
    inline void link(int x, int y) {
        makert(x);
        if (findrt(y) != x) fa[x] = y; 
    }
    
    inline void cut(int x, int y) {
        makert(x);
        if (findrt(y) == x && fa[y] == x && !tr[x][0]) fa[y] = tr[x][1] = 0, pushup(x);
    }
    
    inline void split(int x, int y) {
        makert(x), access(y), splay(y);
    }
    
    int main() {
        n = read(), m = read();
        for (int i = 1; i <= n; i++) val[i] = read();
        for (int i = 1; i <= m; i++) {
            int opt = read(), x = read(), y = read();
            if (opt == 0) split(x, y), write(sum[y]);
            else if (opt == 1) link(x, y);
            else if (opt == 2) cut(x, y);
            else splay(x), val[x] = y;
        }
        return 0;
    }
    View Code

    网络流

    最大流

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    }
    
    inline void write(ll x) {
        if (x < 0) putchar('-'), x = -x;
        if (x == 0) putchar('0');
        else {
            int num = 0; char cc[22];
            while (x) cc[++num] = x % 10 + 48, x /= 10;
            while (num) putchar(cc[num--]);
        }
        putchar('
    ');
    }
    
    const int N = 210, M = 5010;
    
    int n, m, s, t, head[N], nxt[M << 1], to[M << 1], edge[M << 1], cnt = 1;
    
    void add_edge(int u, int v, int w) {
        to[++cnt] = v;
        edge[cnt] = w;
        nxt[cnt] = head[u];
        head[u] = cnt;
    }
    
    queue<int> q; int d[N];
    
    bool bfs() {
        for (int i = 1; i <= n; i++) d[i] = 0;
        while (q.size()) q.pop();
        q.push(s), d[s] = 1;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int i = head[u]; i; i = nxt[i]) {
                int v = to[i];
                if (edge[i] && !d[v]) {
                    d[v] = d[u] + 1;
                    if (v == t) return true;
                    q.push(v);
                }
            }
        }
        return false;
    }
    
    int dinic(int u, int flow) {
        if (u == t) return flow;
        int rest = flow, now;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (edge[i] && d[v] == d[u] + 1) {
                now = dinic(v, min(rest, edge[i]));
                if (!now) d[v] = 0;
                edge[i] -= now, edge[i ^ 1] += now;
                rest -= now;
            }
        }
        return flow - rest;
    }
    
    int main() {
        n = read(), m = read(), s = read(), t = read();
        for (int i = 1; i <= m; i++) {
            int u = read(), v = read(), w = read();
            add_edge(u, v, w), add_edge(v, u, 0);
        }
        int flow = 0; ll maxflow = 0;
        while (bfs()) while (flow = dinic(s, INT_MAX)) maxflow += flow;
        write(maxflow);
        return 0;
    }
    View Code

    费用流

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    }
    
    inline void write(int x, char ch) {
        if (x < 0) putchar('-'), x = -x;
        if (x == 0) putchar('0');
        else {
            int num = 0; char cc[22];
            while (x) cc[++num] = x % 10 + 48, x /= 10;
            while (num) putchar(cc[num--]);
        }
        putchar(ch);
    }
    
    
    const int N = 5e3 + 10, M = 5e4 + 10;
    
    int n, m, s, t, ans;
    
    int head[N], to[M << 1], nxt[M << 1], edge[M << 1], cst[M << 1], cnt = 1, h[N];
    
    void add_edge(int u, int v, int w, int c) {
        to[++cnt] = v, edge[cnt] = w, cst[cnt] = c;
        nxt[cnt] = head[u], head[u] = cnt;
    }
    
    int dis[N]; bool vis[N]; queue<int> q;
    
    bool spfa() {
        for (int i = 1; i <= n; i++) dis[i] = INT_MAX, h[i] = head[i], vis[i] = false;
        while (q.size()) q.pop();
        dis[s] = 0, vis[s] = true, q.push(s);
        while (q.size()) {
            int u = q.front(); vis[u] = false; q.pop();
            for (int i = head[u]; i; i = nxt[i]) {
                int v = to[i];
                if (edge[i] && dis[v] > dis[u] + cst[i]) {
                    dis[v] = dis[u] + cst[i];
                    //if (v == t) return true;
                    if (!vis[v]) q.push(v), vis[v] = true;
                }
            }
        }
        return dis[t] != INT_MAX;
    }
    
    int dinic(int u, int flow) {
        if (u == t) return flow;
        vis[u] = true;
        int rest = flow, now;
        for (int &i = h[u]; i; i = nxt[i]) {
            int v = to[i];
            if (!vis[v] && edge[i] && dis[v] == dis[u] + cst[i]) {
                now = dinic(v, min(rest, edge[i]));
                if (now == 0) dis[v] = INT_MAX;
                edge[i] -= now, edge[i ^ 1] += now, rest -= now;
                ans += now * cst[i];
            }
        }
        return flow - rest;
    }
    
    int main() {
        n = read(), m = read(), s = read(), t = read();
        for (int i = 1; i <= m; i++) {
            int u = read(), v = read(), w = read(), c = read();
            add_edge(u, v, w, c), add_edge(v, u, 0, -c);
        }
        int flow = 0, maxflow = 0;
        while (spfa()) while (flow = dinic(s, 5000000)) maxflow += flow;
        write(maxflow, ' '), write(ans, '
    ');
        return 0;
    }
    View Code

    无源汇上下界可行流

    void add_edge(int u, int v, int w) {
        to[++cnt] = v, edge[cnt] = w, nxt[cnt] = head[u], head[u] = cnt;
    }
    
    void addedge(int u, int v, int w) {
        add_edge(u, v, w), add_edge(v, u, 0);
    }
    
    queue<int> q; int d[N];
    
    bool bfs() {
        while (q.size()) q.pop();
        for (int i = 0; i <= t; i++) d[i] = 0, h[i] = head[i];
        q.push(s), d[s] = 1;
        while (q.size()) {
            int u = q.front(); q.pop();
            for (int i = head[u]; i; i = nxt[i]) {
                int v = to[i];
                if (edge[i] && !d[v]) {
                    d[v] = d[u] + 1;
                    if (v == t) return true;
                    q.push(v);
                }
            }
        }
        return false;
    }
    
    int dinic(int u, int flow) {
        if (u == t) return flow;
        int rest = flow, now;
        for (int &i = h[u]; i; i = nxt[i]) {
            int v = to[i];
            if (edge[i] && d[v] == d[u] + 1) {
                now = dinic(v, min(rest, edge[i]));
                edge[i] -= now, edge[i ^ 1] += now, rest -= now;
            }
        }
        return flow - rest;
    }
    
    int main() {
        n = read(), m = read();
        s = 0, t = n + 1;
        for (int i = 1; i <= m; i++) {
            int u = read(), v = read(), down = read(), up = read(); 
            outf[u] += down, inf[v] += down, dow[i] = down, addedge(u, v, up - down);
        }
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            if (inf[i] > outf[i]) addedge(s, i, inf[i] - outf[i]);
            if (inf[i] < outf[i]) addedge(i, t, outf[i] - inf[i]);
        }
        while (bfs()) dinic(s, 0x3f3f3f3f);
        bool flag = false;
        for (int i = head[s]; i; i = nxt[i]) if (!(i & 1)) flag |= (edge[i] != 0);
        if (flag) puts("NO");
        else {
            puts("YES");
            for (int i = 2; i <= (m << 1); i += 2) write(dow[i >> 1] + edge[i ^ 1], '
    ');
        }
        return 0;
    } 
    View Code

    有源汇上下界最大流

    void add_edge(int u, int v, int w) {
        to[++cnt] = v, edge[cnt] = w, nxt[cnt] = head[u], head[u] = cnt;
    }
    
    void addedge(int u, int v, int w) {
        add_edge(u, v, w), add_edge(v, u, 0);
    }
    
    queue<int> q; int d[N];
    
    bool bfs() {
        while (q.size()) q.pop();
        if (T != n + 1) for (int i = 1; i <= n; i++) d[i] = 0, h[i] = head[i];
        else for (int i = 0; i <= T; i++) d[i] = 0, h[i] = head[i];
        q.push(S), d[S] = 1;
        while (q.size()) {
            int u = q.front(); q.pop();
            for (int i = head[u]; i; i = nxt[i]) {
                int v = to[i];
                if (edge[i] && !d[v]) {
                    d[v] = d[u] + 1;
                    if (v == T) return true;
                    q.push(v);
                }
            }
        }
        return false;
    }
    
    int dinic(int u, int flow) {
        if (u == T) return flow;
        int rest = flow, now;
        for (int &i = h[u]; i; i = nxt[i]) {
            int v = to[i];
            if (edge[i] && d[v] == d[u] + 1) {
                now = dinic(v, min(rest, edge[i]));
                edge[i] -= now, edge[i ^ 1] += now, rest -= now;
            }
        }
        return flow - rest;
    }
    
    int main() {
        scanf("%d%d%d%d", &n, &m, &s, &t);
        for (int i = 1; i <= m; i++) {
            int u, v, down, up; scanf("%d%d%d%d", &u, &v, &down, &up);
            f[u] -= down, f[v] += down, addedge(u, v, up - down);
        }
        S = 0, T = n + 1;
        for (int i = 1; i <= n; i++) {
            if (f[i] > 0) addedge(S, i, f[i]);
            if (f[i] < 0) addedge(i, T, -f[i]);
        }
        addedge(t, s, 0x3f3f3f3f);
        long long maxflow = 0;
        while (bfs()) dinic(S, 0x3f3f3f3f);
        for (int i = head[S]; i; i = nxt[i]) if (!(i & 1) && edge[i]) return puts("please go home to sleep"), 0;
        head[s] = nxt[head[s]], head[t] = nxt[head[t]];
        maxflow = edge[cnt], d[S] = d[T] = -1, S = s, T = t;
        while (bfs()) maxflow += dinic(S, 0x3f3f3f3f);
        cout << maxflow << endl;
        return 0;
    }
    View Code

    圆方树

    void tarjan(int u) {
        low[u] = dfn[u] = ++times, stk[++tp] = u, tot++;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (!dfn[v]) {
                tarjan(v);
                if (low[u] > low[v]) low[u] = low[v];
                if (low[v] == dfn[u]) {
                    cnt++;
                    for (int p = 0; p != v; tp--) {
                        val[cnt]++, p = stk[tp];
                        son[cnt].push_back(p);
                        son[p].push_back(cnt);
                    }
                    val[cnt]++;
                    son[cnt].push_back(u);
                    son[u].push_back(cnt);
                }
            }
            else if (low[u] > dfn[v]) low[u] = dfn[v];
        }
    }
    
    cnt = n;
    for (int i = 1; i <= n; i++) if (!dfn[i]) tot = 0, tarjan(i), --tp/*, dfs(i, 0)*/;
    View Code

     

    最近公共祖先

    欧拉序+RMQ

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 5e5 + 10;
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    }
    
    inline void write(int x, char ch) {
        if (x < 0) putchar('-'), x = -x;
        if (x == 0) putchar('0');
        else {
            int num = 0; char cc[22];
            while (x) cc[++num] = x % 10 + 48, x /= 10;
            while (num) putchar(cc[num--]);
        }
        putchar(ch);
    }
    
    int n, m, rt, head[N], to[N << 1], nxt[N << 1], cnt;
    
    void add_edge(int u, int v) {
        to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
    }
    
    int e[N << 1], times, fir[N];
    
    void dfs(int u, int fa) {
        e[++times] = u, fir[u] = times;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa) continue;
            dfs(v, u), e[++times] = u;
        }
    }
    
    int Min[20][N << 1], Log[N << 1];
    
    void init() {
        Log[0] = -1;
        for (int i = 1; i <= times; i++) Log[i] = Log[i >> 1] + 1, Min[0][i] = fir[e[i]];
        for (int k = 1; (1 << k) <= times; k++)
            for (int i = 1; i + (1 << k) - 1 <= times; i++)
                Min[k][i] = min(Min[k - 1][i], Min[k - 1][i + (1 << (k - 1))]);
    }
    
    int MIN(int l, int r) {
        int t = Log[r - l + 1];
        return min(Min[t][l], Min[t][r - (1 << t) + 1]);
    }
    
    int main() {
        n = read(), m = read(), rt = read();
        for (int i = 1; i < n; i++) {
            int u = read(), v = read();
            add_edge(u, v), add_edge(v, u);
        }
        dfs(rt, 0), init();
        for (int i = 1; i <= m; i++) {
            int u = read(), v = read();
            if (fir[u] > fir[v]) swap(u, v);
            write(e[MIN(fir[u], fir[v])], '
    ');
        }
        return 0;
    } 
    View Code

     

    动态DP

    $Theta(nlog^2n)$

    #include <bits/stdc++.h>
    
    #define mul(i, j) res.g[i][j] = max(g[i][0] + p.g[0][j], g[i][1] + p.g[1][j])
    #define lson u << 1, l, mid
    #define rson u << 1 | 1, mid + 1, r
    
    using namespace std;
    
    typedef long long ll;
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    } 
    
    inline void write(int x, char ch) {
        if (x < 0) putchar('-'), x = -x;
        if (x == 0) putchar('0');
        else {
            int num = 0; char cc[22];
            while (x) cc[++num] = x % 10 + 48, x /= 10;
            while (num) putchar(cc[num--]);
        }
        putchar(ch);
    }
    
    inline int max(const int &g, const int &h) {
        return g > h ? g : h;
    }
    
    const int N = 1e5 + 10;
    
    struct mat {
        int g[2][2];
        void set() {
            g[0][0] = g[1][1] = 0, g[0][1] = g[1][0] = -0x3f3f3f3f;
        }
        mat operator * (const mat &p) const {
            mat res;
            mul(0, 0), mul(0, 1), mul(1, 0), mul(1, 1);
            return res;
        }
    } s[N], tr[N << 2];
    
    int n, m, a[N], dp[N][2];
    
    int head[N], to[N << 1], nxt[N << 1], cnt;
    
    void add_edge(int u, int v) {
        to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
    }
    
    int sze[N], hea[N], dfn[N], tp[N], ed[N], f[N], id[N], times;
    
    void dfs1(int u, int fa) {
        sze[u] = 1, f[u] = fa, dp[u][1] = a[u];
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa) continue;
            dfs1(v, u), sze[u] += sze[v];
            if (sze[hea[u]] < sze[v]) hea[u] = v;
            dp[u][1] += dp[v][0], dp[u][0] += max(dp[v][0], dp[v][1]);
        }
    }
    
    void dfs2(int u, int t) {
        dfn[u] = ed[t] = ++times, id[times] = u, tp[u] = t, s[u].g[1][0] = a[u];
        if (hea[u]) dfs2(hea[u], t);
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == f[u] || v == hea[u]) continue;
            dfs2(v, v);
            s[u].g[1][0] += dp[v][0], s[u].g[0][0] += max(dp[v][0], dp[v][1]);
        }
        s[u].g[0][1] = s[u].g[0][0], s[u].g[1][1] = -0x3f3f3f3f;
    }
    
    void build(int u, int l, int r) {
        if (l == r) tr[u] = s[id[l]];
        else {
            int mid = (l + r) >> 1;
            build(lson), build(rson);
            tr[u] = tr[u << 1] * tr[u << 1 | 1];
        }
    }
    
    mat query(int u, int l, int r, int Left, int Right) {
        if (Left <= l && r <= Right) return tr[u];
        int mid = (l + r) >> 1; mat res; res.set();
        if (Left <= mid) res = res * query(lson, Left, Right);
        if (mid < Right) res = res * query(rson, Left, Right);
        return res;
    }
    
    void modify(int u, int l, int r, int pos) {
        if (l == r) tr[u] = s[id[l]];
        else {
            int mid = (l + r) >> 1;
            if (pos <= mid) modify(lson, pos);
            else modify(rson, pos);
            tr[u] = tr[u << 1] * tr[u << 1 | 1];
        }
    }
    
    void updata(int x, int y) {
        s[x].g[1][0] += y - a[x], a[x] = y;
        while (x) {
            mat las = query(1, 1, n, dfn[tp[x]], ed[tp[x]]);
            modify(1, 1, n, dfn[x]);
            mat now = query(1, 1, n, dfn[tp[x]], ed[tp[x]]);
            x = f[tp[x]];
            s[x].g[0][0] += max(now.g[0][0], now.g[1][0]) - max(las.g[0][0], las.g[1][0]);
            s[x].g[1][0] += now.g[0][0] - las.g[0][0];
            s[x].g[0][1] = s[x].g[0][0];
        }
    }
    
    int main() {
        n = read(), m = read();
        for (int i = 1; i <= n; i++) a[i] = read();
        for (int i = 1; i < n; i++) {
            int u = read(), v = read();
            add_edge(u, v), add_edge(v, u);
        }
        dfs1(1, 0), dfs2(1, 1), build(1, 1, n);
        for (int i = 1; i <= m; i++) {
            int x = read(), y = read(); updata(x, y);
            mat ans = query(1, 1, n, dfn[1], ed[1]);
            write(max(ans.g[0][0], ans.g[1][0]), '
    ');
        }
        return 0;
    }
    View Code

    $Theta(nlog n)$

    #include <bits/stdc++.h>
    
    #define mul(i, j) res.g[i][j] = max(g[i][0] + p.g[0][j], g[i][1] + p.g[1][j])
    #define isroot(u) (ls[f[u]] != u && rs[f[u]] != u)
    
    using namespace std;
    
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    } 
    
    inline void write(int x, char ch) {
        if (x < 0) putchar('-'), x = -x;
        if (x == 0) putchar('0');
        else {
            int num = 0; char cc[22];
            while (x) cc[++num] = x % 10 + 48, x /= 10;
            while (num) putchar(cc[num--]);
        }
        putchar(ch);
    }
    
    inline int max(const int &g, const int &h) {
        return g > h ? g : h;
    }
    
    
    const int N = 1e6 + 10;
    
    int n, m, val[N], root, f[N], ls[N], rs[N], lasans;
    
    int head[N], to[N << 1], nxt[N << 1], cnt;
    
    void add_edge(int u, int v) {
        to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
    }
    
    struct Matrix {
        int g[2][2];
        Matrix operator * (const Matrix p) const {
            Matrix res;
            mul(0, 0), mul(0, 1), mul(1, 0), mul(1, 1);
            return res;
        } 
    } dat[N], mat[N];
    
    int sze[N], lsze[N], hea[N], dp[N][2], id[N], pre[N], tot;
    
    void pushup(int u) {
        mat[u] = dat[u];
        if (ls[u]) mat[u] = mat[ls[u]] * mat[u];
        if (rs[u]) mat[u] = mat[u] * mat[rs[u]];
    }
    
    void dfs1(int u, int fa) {
        sze[u] = lsze[u] = 1, dp[u][1] = val[u];
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa) continue;
            dfs1(v, u), sze[u] += sze[v];
            if (sze[hea[u]] < sze[v]) hea[u] = v;
        }
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa || v == hea[u]) continue;
            dp[u][0] += max(dp[v][0], dp[v][1]);
            dp[u][1] += dp[v][0], lsze[u] += lsze[v];
        }
        dat[u].g[0][0] = dat[u].g[0][1] = dp[u][0];
        dat[u].g[1][0] = dp[u][1], dat[u].g[1][1] = -0x3f3f3f3f;
        dp[u][0] += max(dp[hea[u]][0], dp[hea[u]][1]);
        dp[u][1] += dp[hea[u]][0];
    }
    
    int build(int l, int r) {
        int mid = lower_bound(pre + l, pre + r + 1, (pre[l - 1] + pre[r]) >> 1) - pre, u = id[mid];
        if (l < mid) f[ls[u] = build(l, mid - 1)] = u;
        if (mid < r) f[rs[u] = build(mid + 1, r)] = u;
        pushup(u);
        return u;
    }
    
    void updata(int u) {
        Matrix las = mat[u];
        pushup(u);
        int fa = f[u];
        if (fa && isroot(u)) {
            Matrix now = mat[u];
            dat[fa].g[0][1] = (dat[fa].g[0][0] += max(now.g[0][0], now.g[1][0]) - max(las.g[0][0], las.g[1][0]));
            dat[fa].g[1][0] += now.g[0][0] - las.g[0][0];
        }
        if (fa) updata(fa);
    }
    
    int dfs2(int u, int fa) {
        //cout << u << " " << fa << endl;
        id[++tot] = u, pre[tot] = pre[tot - 1] + lsze[u];
        int rt;
        if (hea[u]) rt = dfs2(hea[u], u);
        else return build(1, tot);
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa || v == hea[u]) continue;
            tot = 0, f[dfs2(v, u)] = u;
        }
        return rt;
    }
    
    int main() {
        n = read(), m = read();
        for (int i = 1; i <= n; i++) val[i] = read();
        for (int i = 1; i < n; i++) {
            int u = read(), v = read();
            add_edge(u, v), add_edge(v, u);
        }
        dfs1(1, 0), root = dfs2(1, 0);
        for (int i = 1; i <= m; i++) {
            int x = read() ^ lasans, y = read();
            dat[x].g[1][0] += y - val[x], val[x] = y;
            updata(x);
            write(lasans = max(mat[root].g[0][0], mat[root].g[1][0]), '
    ');
        }
        return 0;
    }
    View Code

    虚树

    void ins(int x) {
        if (tp <= 1) return stk[++tp] = x, void();
        int lca = Lca(x, stk[tp]);
        if (lca != stk[tp]) {
            while (tp > 1 && dfn[lca] <= dfn[stk[tp - 1]]) son[stk[tp - 1]].push_back(stk[tp]), tp--;
            if (lca != stk[tp]) son[lca].push_back(stk[tp]), stk[tp] = lca;
        }
        stk[++tp] = x;
    }
    
    
    sort(id + 1, id + m + 1, cmp);
    tp = 0; if (id[1] != 1) stk[tp = 1] = 1;
    for (int i = 1; i <= m; i++) ins(id[i]);
    while (tp > 1) son[stk[tp - 1]].push_back(stk[tp]), tp--;
    View Code

    2-sat及构造解

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    }
    
    inline void write(int x, char ch) {
        if (x < 0) putchar('-'), x = -x;
        if (x == 0) putchar('0');
        else {
            int num = 0; char cc[22];
            while (x) cc[++num] = x % 10 + 48, x /= 10;
            while (num) putchar(cc[num--]);
        }
        putchar(ch);
    }
    
    const int N = 1e6 + 10;
    
    int n, m, head[N << 1], to[N << 1], nxt[N << 1], cnt;
    
    void add_edge(int u, int v) {
        to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
    }
    
    int dfn[N << 1], low[N << 1], times, stk[N << 1], tp, id[N << 1], tot; bool ins[N << 1];
    
    void tarjan(int u) {
        dfn[u] = low[u] = ++times;
        stk[++tp] = u, ins[u] = true;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (!dfn[v]) {
                tarjan(v);
                if (low[u] > low[v]) low[u] = low[v];
            }
            else if (ins[v] && low[u] > dfn[v]) low[u] = dfn[v];
        }
        if (dfn[u] == low[u]) {
            tot++; int v;
            do {
                v = stk[tp--], ins[v] = false, id[v] = tot; 
            } while (u != v);
        } 
    }
    
    int main() {
        n = read(), m = read();
        for (int i = 1; i <= m; i++) {
            int x = read(), a = read(), y = read(), b = read();
            add_edge(x + (((a ^ 1) & 1) ? n : 0), y + ((b & 1) ? n : 0));
            add_edge(y + (((b ^ 1) & 1) ? n : 0), x + ((a & 1) ? n : 0));
        }
        for (int i = 1; i <= (n << 1); i++) if (!dfn[i]) tarjan(i);
        for (int i = 1; i <= n; i++) if (id[i] == id[n + i]) return puts("IMPOSSIBLE"), 0;
        puts("POSSIBLE");
        for (int i = 1; i <= n; i++) write(id[n + i] < id[i], ' ');
        return 0;
    }
    View Code

    欧拉回路

     

    左偏树

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    }
    
    inline void write(int x, char ch) {
        if (x < 0) putchar('-'), x = -x;
        if (x == 0) putchar('0');
        else {
            int num = 0; char cc[22];
            while (x) cc[++num] = x % 10 + 48, x /= 10;
            while (num) putchar(cc[num--]);
        }
        putchar(ch);
    }
    
    
    const int N = 1e5 + 10;
    
    int n, m, val[N], dis[N], fa[N], ls[N], rs[N]; 
    
    bool del[N];
    
    int find(int u) {
        return fa[u] == u ? u : fa[u] = find(fa[u]);
    }
    
    int merge(int x, int y) {
        if (!x || !y) return x | y;
        if (val[x] > val[y] || (val[x] == val[y] && x > y)) swap(x, y);
        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;
    }
    
    int main() {
        n = read(), m = read();
        for (int i = 1; i <= n; i++) val[i] = read(), fa[i] = i;
        for (int i = 1; i <= m; i++) {
            int opt = read();
            if (opt == 1) {
                int x = read(), y = read();
                if (del[x] || del[y]) continue;
                x = find(x), y = find(y);
                if (x != y) fa[x] = fa[y] = merge(x, y);
            }
            else {
                int x = read();
                if (del[x]) puts("-1");
                else {
                    x = find(x), del[x] = true, write(val[x], '
    ');
                    if (!ls[x] && !rs[x]) continue;
                    if (!rs[x]) fa[x] = fa[ls[x]] = ls[x];
                    else fa[ls[x]] = fa[rs[x]] = fa[x] = merge(ls[x], rs[x]);
                }
            }
        }
        return 0;
    }
    View Code

     

    笛卡尔树

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    }
    
    const int N = 1e7 + 10;
    
    int n, val[N], stk[N], tp, cur, ls[N], rs[N];
    
    long long ansl, ansr;
    
    int main() {
        n = read();
        for (int i = 1; i <= n; i++) {
            val[i] = read();
            cur = tp;
            while (cur && val[stk[cur]] > val[i]) cur--;
            if (cur) rs[stk[cur]] = i;
            if (cur < tp) ls[i] = stk[cur + 1];
            tp = cur, stk[++tp] = i;
        }
        for (int i = 1; i <= n; i++) ansl ^= (ls[i] + 1ll) * i, ansr ^= (rs[i] + 1ll) * i;
        printf("%lld %lld
    ", ansl, ansr);
        return 0;
    }
    View Code

    点分治

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    }
    
    const int N = 1e4 + 10;
    
    int n, m, k, que[110], rt, sze[N], Max[N], sum; bool ans[110];
    
    int head[N], to[N << 1], nxt[N << 1], edge[N << 1], cnt;
    
    void add_edge(int u, int v, int w) {
        to[++cnt] = v, edge[cnt] = w, nxt[cnt] = head[u], head[u] = cnt;
    }
    
    bool vis[N], p[10000010]; int dis[N], stk[N], tp; 
    
    void calc(int u, int fa) {
        sze[u] = 1, Max[u] = 0; 
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa || vis[v]) continue;
            calc(v, u), sze[u] += sze[v];
            if (Max[u] < sze[v]) Max[u] = sze[v];
        }
        if (Max[u] < sum - sze[u]) Max[u] = sum - sze[u];
        if (Max[rt] > Max[u]) rt = u;
    }
    
    void add(int u, int fa) {
        if (dis[u] <= 10000000) stk[++tp] = dis[u];
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i]; 
            if (v == fa || vis[v]) continue;
            dis[v] = dis[u] + edge[i], add(v, u);
        }
    }
    
    void clean(int u, int fa) {
        if (dis[u] <= 10000000) p[dis[u]] = false;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i]; 
            if (v == fa || vis[v]) continue;
            clean(v, u);
        }
    }
    
    void dfs(int u, int fa) {
        //cout << u << ',' << fa << endl;
        vis[u] = p[dis[u] = 0] = true;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa || vis[v]) continue;
            dis[v] = edge[i], add(v, u);
            //cout << v << " " << tp << endl;
            //cout << stk[tp] << " " << dis[stk[tp]] << " " << edge[i] << endl;
            for (int j = 1; j <= tp; j++)
                for (int k = 1; k <= m; k++) if (que[k] >= stk[j]) ans[k] |= p[que[k] - stk[j]];
            while (tp > 0) p[stk[tp--]] = true;
        }
        clean(u, fa);
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa || vis[v]) continue;
            sum = sze[v], Max[rt = 0] = 0x3f3f3f3f, calc(v, u), calc(rt, 0), dfs(rt, u);
        }
    }
    
    int main() {
        n = read(), m = read();
        for (int i = 1; i < n; i++) {
            int u = read(), v = read(), w = read();
            add_edge(u, v, w), add_edge(v, u, w);
        }
        for (int i = 1; i <= m; i++) que[i] = read();
        sum = n, Max[0] = 0x3f3f3f3f, calc(1, 0), calc(rt, 0), dfs(rt, 0);
        for (int i = 1; i <= m; i++) puts(ans[i] ? "AYE" : "NAY");
        return 0;
    }
    View Code

    点分树

    #include <bits/stdc++.h>
    
    typedef long long ll;
    
    using namespace std;
    
    inline int read() {
        int out = 0; bool flag = false;
        register char cc = getchar();
        while (cc < '0' || cc > '9') {
            if (cc == '-') flag = true;
            cc = getchar();
        }
        while (cc >= '0' && cc <= '9') {
            out = (out << 3) + (out << 1) + (cc ^ 48);
            cc = getchar();
        }
        return flag ? -out : out;
    }
    
    inline void write(int x, char ch) {
        if (x < 0) putchar('-'), x = -x;
        if (x == 0) putchar('0');
        else {
            int num = 0; char cc[22];
            while (x) cc[++num] = x % 10 + 48, x /= 10;
            while (num) putchar(cc[num--]);
        }
        putchar(ch);
    }
    
    const int N = 1e5 + 10, MAXN = 8e6 + 10;
    
    int n, m, val[N], las;
    
    int head[N], to[N << 1], nxt[N << 1], cnt;
    
    void add_edge(int u, int v) {
        to[++cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
    }
    
    int dep[N], e[N << 1], fir[N], times, Min[18][N << 1], Log[N << 1];
    
    void pre(int u, int fa) {
        e[++times] = u, fir[u] = times, dep[u] = dep[fa] + 1;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa) continue;
            pre(v, u), e[++times] = u;
        }
    }
    
    void init() {
        Log[0] = -1;
        for (int i = 1; i <= times; i++) Log[i] = Log[i >> 1] + 1, Min[0][i] = fir[e[i]];
        for (int k = 1; (1 << k) <= times; k++) {
            for (int i = 1; i + (1 << k) - 1 <= times; i++) 
                Min[k][i] = min(Min[k - 1][i], Min[k - 1][i + (1 << (k - 1))]);
        }
    }
    
    int Lca(int x, int y) {
        x = fir[x], y = fir[y];
        if (x > y) swap(x, y);
        int t = Log[y - x + 1];
        return e[min(Min[t][x], Min[t][y - (1 << t) + 1])];
    }
    
    vector<int> son[N]; int sze[N], Max[N], sum, rt, f[N]; bool vis[N];
    
    void calc(int u, int fa) {
        sze[u] = 1, Max[u] = 0;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa || vis[v]) continue;
            calc(v, u), sze[u] += sze[v];
            if (Max[u] < sze[v]) Max[u] = sze[v];
        }
        if (Max[u] < sum - sze[u]) Max[u] = sum - sze[u];
        if (Max[rt] > Max[u]) rt = u;
    }
    
    void calc(int u) {
        sze[u] = 1;
        for (auto v : son[u]) calc(v), sze[u] += sze[v];
    } 
    
    int dfs(int u, int fa) {
        vis[u] = true;
        for (int i = head[u]; i; i = nxt[i]) {
            int v = to[i];
            if (v == fa || vis[v]) continue;
            sum = sze[u], rt = 0, calc(v, u), calc(rt, 0);
            son[u].push_back(rt), f[rt] = u;
            dfs(rt, u);
        }
        return u;
    }
    
    int root[N], ls[MAXN], rs[MAXN], nodeid, s[MAXN], frt[N];
    
    #define lson ls[u], l, mid
    #define rson rs[u], mid + 1, r
    
    void modify(int &u, int l, int r, int pos, int delta) {
        if (!u) u = ++nodeid;
        if (l == r) s[u] += delta;
        else {
            int mid = (l + r) >> 1;
            if (pos <= mid) modify(lson, pos, delta);
            else modify(rson, pos, delta);
            s[u] = s[ls[u]] + s[rs[u]];
        }
    }
    
    int query(int u, int l, int r, int Left, int Right) {
        if (Left <= l && r <= Right) return s[u];
        int mid = (l + r) >> 1, res = 0;
        if (ls[u] && Left <= mid) res += query(lson, Left, Right);
        if (rs[u] && mid < Right) res += query(rson, Left, Right);
        return res;
    }
    
    void build(int u, int p) {
        modify(root[p], 0, sze[p] - 1, dep[u] + dep[p] - (dep[Lca(u, p)] << 1), val[u]);
        if (f[p]) modify(frt[p], 0, sze[p], dep[u] + dep[f[p]] - (dep[Lca(u, f[p])] << 1), val[u]);
        for (auto v : son[u]) build(v, p);
    }
    
    int main() {
        //freopen("1.in", "r", stdin);
        //freopen("1.out", "w", stdout); 
        n = read(), m = read();
        for (int i = 1; i <= n; i++) val[i] = read();
        for (int i = 1; i < n; i++) {
            int u = read(), v = read();
            add_edge(u, v), add_edge(v, u);
        }
        pre(1, 0), init();
        sum = n, Max[rt = 0] = 0x3f3f3f3f;
        calc(1, 0), calc(rt, 0), rt = dfs(rt, 0);
        calc(rt);
        for (int i = 1; i <= n; i++) build(i, i);
        for ( ; m; m--) {
            int op = read(), x = read() ^ las, y = read() ^ las;
            if (op == 0) {
                las = query(root[x], 0, sze[x] - 1, 0, y);
                int u = f[x], v = x;
                while (u) {
                    int dis = dep[u] + dep[x] - (dep[Lca(u, x)] << 1);
                    if (dis > y) {
                        v = u, u = f[u];
                        continue;
                    }
                    las -= query(frt[v], 0, sze[v], 0, y - dis);
                    las += query(root[u], 0, sze[u] - 1, 0, y - dis);
                    v = u, u = f[u];
                }
                write(las, '
    ');
            }
            else {
                int u = x;
                while (u) {
                    modify(root[u], 0, sze[u] - 1, dep[u] + dep[x] - (dep[Lca(u, x)] << 1), y - val[x]);
                    if (f[u]) modify(frt[u], 0, sze[u], dep[f[u]] + dep[x] - (dep[Lca(f[u], x)] << 1), y - val[x]);
                    u = f[u];
                }
                val[x] = y;
            }
        }
        return 0;
    }
    View Code

    单纯形

    #include <bits/stdc++.h>
    
    #define eps 1e-6
    #define inf 1e9
    
    using namespace std;
    
    const int N = 1e3 + 10, M = 1e4 + 10;
    
    int n, m;
    
    double a[M][N], b[N], c[M], v;
    
    void pivot(int l, int e) {
        c[l] /= a[l][e];
        for (int j = 1; j <= n; j++) if (j != e) a[l][j] /= a[l][e];
        a[l][e] = 1.0 / a[l][e];
        for (int i = 1; i <= m; i++) if (i != l && fabs(a[i][e]) > eps) {
            c[i] -= c[l] * a[i][e];
            for (int j = 1; j <= n; j++) if (j != e) a[i][j] -= a[l][j] * a[i][e];
            a[i][e] *= -a[l][e];
        }
        v += b[e] * c[l];
        for (int j = 1; j <= n; j++) if (j != e) b[j] -= b[e] * a[l][j];
        b[e] *= -a[l][e];
    } 
    
    double simplex() {
        while (true) {
            int e = -1, l = -1;
            for (int j = 1; j <= n; j++) 
                if (b[j] > eps) {
                    e = j;
                    break;
                }
            if (e == -1) return v;
            double tmp = inf;
            for (int i = 1; i <= m; i++)
                if (a[i][e] > eps && c[i] / a[i][e] < tmp) l = i, tmp = c[i] / a[i][e];
            if (l == -1) return inf;
            pivot(l, e);
        }
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        for (int j = 1; j <= n; j++) scanf("%lf", &b[j]);
        for (int i = 1; i <= m; i++) {
            int l, r; scanf("%d%d%lf", &l, &r, &c[i]);
            for (int j = l; j <= r; j++) a[i][j] = 1;
        }
        printf("%d", (int)(simplex() + 0.5));
        return 0;
    }
    View Code
  • 相关阅读:
    【数论】线性模方程
    【数论】拓展欧几里得
    BZOJ1433: [ZJOI2009]假期的宿舍
    BZOJ2823: [AHOI2012]信号塔
    BZOJ1088: [SCOI2005]扫雷Mine
    BZOJ1257: [CQOI2007]余数之和sum
    BZOJ1227: [SDOI2009]虔诚的墓主人
    BZOJ1856: [Scoi2010]字符串
    BZOJ1084: [SCOI2005]最大子矩阵
    BZOJ2007: [Noi2010]海拔
  • 原文地址:https://www.cnblogs.com/Urushibara-Ruka/p/14547120.html
Copyright © 2011-2022 走看看