线段树:
#include <bits/stdc++.h> using namespace std; #define ls rt << 1 #define rs rt << 1 | 1 #define rep(i, a, b) for (register int i = (a); i <= (b); i++) const int maxn = 1e5 + 5; int n, m; int a[maxn]; struct segment_tree { int l, r, sum, lazy; #define l(x) T[x].l #define r(x) T[x].r #define sum(x) T[x].sum #define lazy(x) T[x].lazy #define length(x) (r(x) - l(x) + 1) }T[maxn << 2]; int read() { int x = 0, flag = 0; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') { flag = 1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + ch - '0'; ch = getchar(); } return flag ? -x : x; } void build(int rt, int l, int r) { l(rt) = l, r(rt) = r; if (l == r) { sum(rt) = a[l]; return; } int mid = (l + r) >> 1; build(ls, l, mid); build(rs, mid + 1, r); sum(rt) = sum(ls) + sum(rs); } void spread(int rt) { if (lazy(rt)) { sum(ls) += lazy(rt) * length(ls); sum(rs) += lazy(rt) * length(rs); lazy(ls) += lazy(rt); lazy(rs) += lazy(rt); lazy(rt) = 0; } } void change(int rt, int l ,int r, int k) { if (l <= l(rt) && r(rt) <= r) { sum(rt) += k * length(rt); lazy(rt) += k; return; } int mid = (l(rt) + r(rt)) >> 1; if (l <= mid) change(ls, l, r, k); if (r > mid) change(rs, l, r, k); spread(rt); sum(rt) = sum(ls) + sum(rs); } int query(int rt, int l, int r) { if (l <= l(rt) && r(rt) <= r) return sum(rt); spread(rt); int mid = (l(rt) + r(rt)) >> 1; int ans = 0; if (l <= mid) ans += query(ls, l, r); if (r > mid) ans += query(rs, l, r); return ans; } void write(int x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x / 10); putchar(x % 10 + '0'); } int main() { n = read(), m = read(); rep(i, 1, n) a[i] = read(); build(1, 1, n); while (m--) { int opt, x, y, k; opt = read(), x = read(), y = read(); if (opt == 1) { k = read(); change(1, x, y, k); } else { write(query(1, x, y)); printf("\n"); } } return 0; }
区间动规:
rep(p, 2, n) for (register int i = 1, j = i + p - 1; j <= n; i++, j = i + p - 1) rep(k, i, j - 1) dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + val[i][j]); write(dp[1][n]);
数位动规:
顺序版:
//大部分时候DP数组并不需要开这么多维. void origin() {memset(dp, -1, sizeof(dp));} int dfs(int pos, int pre, int limit, int lead, int sum, ???) { int ans = 0; if (pos > len) return sum; if (!limit && !lead && dp[pos][pre][limit][lead][sum]??? != -1) return dp[pos][pre][limit][lead][sum]???; int res = limit ? num[len - pos + 1] : 9; rep(i, 0, res) { if (!i && lead) ans += dfs(pos + 1, 0, (i == res) && limit, 1, ???); else if (i && lead) ans += dfs(pos + 1, i, (i == res) && limit, 0, ???); else if(/*根据题意而设的判断*/) ans += dfs(pos + 1, ???, (i == res) && limit, ???); } if (!limit && !lead) dp[pos][pre][limit][lead][sum]??? = ans; return ans; } int work(int x) { origin(); len = 0; while(x) { num[++len] = x % 10; x /= 10; } return dfs(1, 0, 1, 1, 0, ???); } int main() { l = read(), r = read(); write(work(r) - work(l - 1)); return 0; }
逆序版:
//大部分时候DP数组并不需要开这么多维. void origin() {memset(dp, -1, sizeof(dp));} int dfs(int pos, int pre, int limit, int lead, int sum, ???) { int ans = 0; if (!pos) return sum; if (!limit && !lead && dp[pos][pre][limit][lead][sum]??? != -1) return dp[pos][pre][limit][lead][sum]???; int res = limit ? num[pos] : 9; rep(i, 0, res) { if (!i && lead) ans += dfs(pos - 1, 0, (i == res) && limit, 1, ???); else if (i && lead) ans += dfs(pos - 1, i, (i == res) && limit, 0, ???); else if(/*根据题意而设的判断*/) ans += dfs(pos - 1, ???, (i == res) && limit, ???); } if (!limit && !lead) dp[pos][pre][limit][lead][sum]??? = ans; return ans; } int work(int x) { origin(); len = 0; while(x) { num[++len] = x % 10; x /= 10; } return dfs(len, 0, 1, 1, 0, ???); } int main() { l = read(), r = read(); write(work(r) - work(l - 1)); return 0; }
网络最大流:
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (register int i = (a); i <= (b); i++) const int inf = 0x3f3f3f3f, maxn = 1e4 + 5, maxm = 1e6 + 5; int n, m, S, T, ans = 0, num_edge = -1; int cur[maxn], dep[maxn], head[maxn]; queue<int> q; struct node { int to, dis, nxt; }edge[maxm]; void origin() {memset(head, -1, sizeof(head));} int read() { int x = 0, flag = 0; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') { flag = 1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + ch - '0'; ch = getchar(); } return flag ? -x : x; } void addedge(int from, int to, int dis) { edge[++num_edge].nxt = head[from]; edge[num_edge].to = to; edge[num_edge].dis = dis; head[from] = num_edge; } int bfs(int S, int T) { memset(dep, 0, sizeof(dep)); while (!q.empty()) q.pop(); memcpy(cur, head, sizeof(cur)); dep[S] = 1; q.push(S); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; ~i; i = edge[i].nxt) { int v = edge[i].to; if (!dep[v] && edge[i].dis) { dep[v] = dep[u] + 1; q.push(v); } } } if (dep[T]) return 1; return 0; } int dfs(int u, int flow) { if (u == T || !flow) return flow; int d, used = 0; for (int i = cur[u]; ~i; i = edge[i].nxt) { cur[u] = i; int v = edge[i].to; if (dep[v] == dep[u] + 1 && (d = dfs(v, min(flow, edge[i].dis)))) { used += d; flow -= d; edge[i].dis -= d; edge[i ^ 1].dis += d; if (!flow) break; } } if (!used) dep[u] = -2; return used; } int dinic() { int ans = 0; while (bfs(S, T)) ans += dfs(S, inf); return ans; } void write(int x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x / 10); putchar(x % 10 + '0'); } int main() { origin(); n = read(), m = read(), S = read(), T = read(); rep(i, 1, m) { int u, v, w; u = read(), v = read(), w = read(); addedge(u, v, w); addedge(v, u, 0); } ans = dinic(); write(ans); return 0; }