OI常见模板集合

线段树:

#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;
}
View Code

 

区间动规:

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]);
View Code

 

数位动规:

顺序版:

//大部分时候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;
}
View Code

 

逆序版:

//大部分时候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;
}
View Code

 

网络最大流:

#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;
}
View Code

 

转载于:https://www.cnblogs.com/Kirisame-Marisa/p/11004693.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值