CF865D Buy Low Sell High
传送门
题意:已知未来
天的股价 ,每天可以买入一支或者卖出一支,求 天后利润总额最大是多少。
算法:模拟费用流。
【费用流模型】
把每一天抽象为一个结点:
求最大费用任意流,意思就是不限制流量但是要求费用最大。
这种任意流有一个特点:就是费用为负数的增广路一定不会流。(很显然吧)
【模拟费用流】
直接费用流显然不行,传统的模拟费用流(整体考虑)不太好维护(因为
在这里提出一种新的模型:"增量-最大费用任意流模型"。(名字取自 command_block 的博客)
具体而言,每次增加一部分边/点,直到增加了所有边/点。增加后的最大费用任意流相较于增加前的最大费用任意流,只需要考虑三种东西的贡献:
-
新的增广路。
-
包含源点的正环。
-
包含汇点的正环。
当然上面三种东西,都必须涉及新加入的边。
所以可以画出这样的图:
黑色是原本的图,红色是新加的点和边,两条绿色是可能的新增负环和增广路。
上面的增广路,要求
注意这里不考虑
可以用两个 set 维护。因为新增的
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int n;
int c[300005];
multiset<int> s1, s2; //s1是上层没用过的边,s2是下层用过的边
long long sum = 0;
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> c[i];
s1.insert(c[1]);
for (int i = 2; i <= n; i++) {
int a = -1, b = -1;
if (!s1.empty())
a = *s1.begin();
if (!s2.empty())
b = *s2.begin();
if (a != -1 && (a <= b || b == -1)) {
if (c[i] >= a) {
sum += c[i] - a;
s2.insert(c[i]);
s1.erase(s1.find(a));
}
else
s1.insert(c[i]);
}
else if (b != -1 && (b <= a || a == -1)) {
if (c[i] >= b) {
sum += c[i] - b;
s1.insert(b);
s2.erase(s2.find(b));
s2.insert(c[i]);
}
else
s1.insert(c[i]);
}
}
cout << sum << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!