P7730 [JDWOI-1] 蜀道难 题解

思路#

考虑费用流。

发现区间操作与单调不降。

考虑差分。

ai=hihi1

那么我们需要让所有的 ai 全部都变为自然数。

考虑一次区间操作的影响。

对于 (+,l,r),我们会让 al 加一,ar+1 减一。

对于 (,l,r),我们会让 al 减一,ar+1 加一。

那么我们可以建出以下费用流模型。

对于 ai>0,连 (s,i,ai,0),表示可以减 ai 次。

对于 ai<0,连 (i,t,ai,0),表示必须加 ai 次。

可以连 (s,n+1,inf,0) 补充流量。

对于 (+,l,c),每一个点连 (i,il,inf,c)

对于 (,l,c),每一个点连 (i,i+l,inf,c)

然后跑费用流即可。

当然,值得一提的是,注:所有时候山的高度都不能为负,所以 h0=0

Code#

/*
  ! 如果没有天赋,那就一直重复
  ! Created: 2024/06/03 14:23:49
*/
#include <bits/stdc++.h>
using namespace std;

#define fro(i, x, y) for (int i = (x); i <= (y); i++)
#define pre(i, x, y) for (int i = (x); i >= (y); i--)

struct NetWork {
  using i64 = long long;
  struct edge { int to, nxt; i64 v, c; };
  int ct, n, s, t; i64 mf, mc;
  vector<int> dp, cr, hd, vs;
  vector<i64> ds;
  vector<edge> e;
  inline NetWork(int N) {
    vs.resize(N + 5), n = N, ct = 1;
    dp.resize(N + 5), ds.resize(N + 5);
    cr.resize(N + 5), hd.resize(N + 5);
    e.push_back({}), e.push_back({});
  }
  inline void add(int x, int y, int z, int u) {
    e.push_back({y, hd[x], z, u}), hd[x] = ++ct;
    e.push_back({x, hd[y], 0,-u}), hd[y] = ++ct;
  }
  inline bool bfs() {
    queue<int> q;
    fro(i, 1, n) dp[i] = 0, ds[i] = 1e18, cr[i] = hd[i];
    q.push(s), ds[s] = 0;
    while (q.empty() == 0) {
      int x = q.front(); q.pop(), vs[x] = 0;
      for (int i = hd[x]; i; i = e[i].nxt) {
        if (e[i].v == 0) continue;
        if (ds[e[i].to] > ds[x] + e[i].c) {
          ds[e[i].to] = ds[x] + e[i].c;
          dp[e[i].to] = dp[x] + 1;
          if (!vs[e[i].to]) q.push(e[i].to), vs[e[i].to] = 1;
        }
      }
    }
    return ds[t] != 1e18;
  }
  inline i64 dfs(int now, i64 flow) {
    if (now == t) return mf += flow, flow;
    i64 used = 0;
    for (int&i = cr[now]; i; i = e[i].nxt) {
      if (ds[now] + e[i].c == ds[e[i].to] && dp[now] + 1 == dp[e[i].to] && e[i].v) {
        int x = dfs(e[i].to, min(e[i].v, flow - used));
        e[i].v -= x, e[i ^ 1].v += x, used += x, mc += x * e[i].c;
        if (used == flow) return used;
      }
    }
    return used;
  }
  inline pair<i64, i64> zkw(int S, int T) {
    s = S, t = T, mf = mc = 0;
    while (bfs()) while (dfs(s, 1e18));
    return {mf, mc};
  }
};

signed main() {
  ios::sync_with_stdio(0), cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<int> h(n + 1);
  NetWork sol(n + 3);
  int s = n + 2, t = n + 3;
  fro(i, 1, n) {
    cin >> h[i];
  }
  fro(i, 1, m) {
    char w; int l, c;
    cin >> w >> l >> c;
    if (w == '+') fro(i, 1 + l, n + 1) sol.add(i, i - l, 1e9, c);
    if (w == '-') fro(i, 1 + 0, n - l) sol.add(i, i + l, 1e9, c);
  }
  sol.add(s, n + 1, 1e9, 0);
  pre(i, n, 1) {
    h[i] = h[i] - h[i - 1];
    if (h[i] > 0) sol.add(s, i, h[i], 0);
    if (h[i] < 0) sol.add(i, t,-h[i], 0);
  }
  auto ans = sol.zkw(s, t);
  fro(i, 2, n) if (h[i] < 0) ans.first += h[i];
  cout << (ans.first == 0 ? ans.second : -1) << "\n";
  return 0;
}

作者:JiaY19

出处:https://www.cnblogs.com/JiaY19/p/18229361

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   JiaY19  阅读(6)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示