P7730 [JDWOI-1] 蜀道难 题解
思路#
考虑费用流。
发现区间操作与单调不降。
考虑差分。
令
那么我们需要让所有的
考虑一次区间操作的影响。
对于
对于
那么我们可以建出以下费用流模型。
对于
对于
可以连
对于
对于
然后跑费用流即可。
当然,值得一提的是,注:所有时候山的高度都不能为负,所以
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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 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)