一些需要注意的地方/模板/杂项

光速乘

有用到负数用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
原文地址:https://www.cnblogs.com/Urushibara-Ruka/p/14547120.html