「CTSC2010」产品销售
「CTSC2010」产品销售
30pts的费用流都会吧...
100pts只要模拟费用流就行了,是不是很简单呀(
咕咕咕
令\(M_i\)表示\(i-1\to i\)的正向边,\(M_i^{'}\)表示反向边
\(C_i\)表示\(i \to i-1\)的正向边,\(C_i^{'}\)表示反向边
依次枚举\(1,\cdots,n\)
当前枚举到\(i\),要使\(i\rightarrow t\)满流
两种决策:\(s \rightarrow j \to j+1 \to \cdots \to i\) or \(i \leftarrow i+1 \leftarrow \cdots \leftarrow j \leftarrow s\)
下面表述中,起始位置就是\(j\)。
第二种决策
由于是依次枚举,故\(M_i+1,\cdots,M_j\)并没有流量,则费用为\(\sum_{k=i+1}^j cost[C_k]\)。
由于\(i\)是顺次推过来,故可以直接对\(\sum_{k=1}^j cost[C_k]\)排序,跳过\(k\leq i || U[k]==0\)的点,取最优即可。
第一种决策
对于当前决策,若有一条边\(C_k( j+1\leq k \leq i)\)有流量,那么费用需要减去\(cost[C_k]+cost[M_k]\)。
可行流量为\(min(w[C_k])(w[c_k] \geq 1)\)。
那么可以转化一下:在加入\(k\)这个点的时候,对于始于\([1,k-1]\)的第一种决策的路径,若\(C_k\)有流量,那么全部减去\(cost[C_k]\),否则加上\(cost[M_k]\)。
当\(C_k\)流量减为0时,对始于\([1,k-1]\)的第一种决策的路径全部加上\(cost[M_k]+cost[C_k]\)。
显然对于\(C_k\)修改只会执行2次。
具体讲讲怎么维护吧...
线段树an1维护\(w[C_x]\),an2维护以\(j\)为起始到 当前枚举的点\(i\)的花费。
由于\(an1\)要维护\(min(w[C_x])(w[C_x] \geq1)\),为了方便,初始值设为\(inf\)
第一种决策
an2查询\([1,i]\)的最小值\(Min\),并找到其位置\(k\)。
an1查询\([k+1,i]\)的\(Minf\)= \(min(w[C_x])(w[C_x] \geq1)\) ,并找到其位置。
可行的流量\(flow\)为\(min(U[k],D[i],Minf)\)。
将an1的\([k+1,i]\)全部减去flow,\(U[k]-=flow,D[i]-=flow\)。
对于an1中\(w[C_k]==0\)的点,权值设置为\(inf\),并对an2中\([1,\cdots ,k-1]\)的点加上\(cost[M_k]+cost[C_k]\)。
若\(U[k]==0\),在an2中设置\(k\)权值为\(inf\)。
第二种决策
起始位置为\(k\),可行流量为\(flow=min(U[k],D[i])\)。
首先要将an1\([i+1,k]\)当中权值为\(inf\)的点修改为0,用并查集跳过不是\(inf\)的点即可。
然后将an1\([i+1,k]\)权值加\(flow\),\(U[k]-=flow,D[i]-=flow\)。
枚举到下一个点i+1
将\(i+1\)加入an2中(若\(U[i+1]==0\)设为\(inf\))
在an2中,\([1,i]\)加上\(w[C_{i+1}] \geq 1?-cost[C_{i+1}]:cost[M_{i+1}]\)
其实可以发现an1,an2支持的操作是一样的
#include <bits/stdc++.h>
//#pragma GCC target("avx,avx2,sse4.2")
#define rep(q, a, b) for (int q = a, q##_end_ = b; q <= q##_end_; ++q)
#define dep(q, a, b) for (int q = a, q##_end_ = b; q >= q##_end_; --q)
#define mem(a, b) memset(a, b, sizeof a)
#define debug(a) cerr << #a << ' ' << a << "___" << endl
using namespace std;
// char buf[10000000], *p1 = buf, *p2 = buf;
#define Getchar() \
getchar() // p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 10000000, stdin), p1 == p2) ? EOF : *p1++
void in(int &r) {
static char c;
r = 0;
bool flag(0);
while (c = Getchar(), c < 48) (c == '-') && (flag = 1);
do
r = (r << 1) + (r << 3) + (c ^ 48);
while (c = Getchar(), c > 47);
flag && (r = -r);
}
const int mn = 100005;
const int INF = 2e9;
int n, D[mn], U[mn], P[mn], M[mn], C[mn];
struct node {
int x, v;
bool operator<(const node &A) const { return v < A.v; }
} an1[mn];
struct segment_tree {
int at[mn << 2], addv[mn << 2], y_1, y_2, ad_v, minv[mn << 2];
void build(int o, int l, int r, int v) {
minv[o] = v, at[o] = l;
if (l == r)
return;
int mid = l + r >> 1;
build(o << 1, l, mid, v);
build(o << 1 | 1, mid + 1, r, v);
}
void maintain(int o) {
if (minv[o << 1] + addv[o << 1] < minv[o << 1 | 1] + addv[o << 1 | 1]) {
minv[o] = minv[o << 1] + addv[o << 1];
at[o] = at[o << 1];
} else {
minv[o] = minv[o << 1 | 1] + addv[o << 1 | 1];
at[o] = at[o << 1 | 1];
}
}
void change(int o, int l, int r, int adv) {
adv += addv[o];
if (l == r)
minv[o] = ad_v - adv;
else {
int mid = l + r >> 1;
if (y_1 <= mid)
change(o << 1, l, mid, adv);
else
change(o << 1 | 1, mid + 1, r, adv);
maintain(o);
}
}
void change(int x, int v) {
y_1 = x, ad_v = v;
change(1, 1, n, 0);
}
void modify(int o, int l, int r) {
if (y_1 <= l && r <= y_2)
addv[o] += ad_v;
else {
int mid = l + r >> 1;
if (y_1 <= mid)
modify(o << 1, l, mid);
if (y_2 > mid)
modify(o << 1 | 1, mid + 1, r);
maintain(o);
}
}
void add(int l, int r, int v) {
if (l > r)
return;
y_1 = l, y_2 = r, ad_v = v;
modify(1, 1, n);
}
int Min, At;
void ask(int o, int l, int r, int adv) {
adv += addv[o];
if (y_1 <= l && r <= y_2) {
if (minv[o] + adv < Min)
Min = minv[o] + adv, At = at[o];
return;
}
int mid = l + r >> 1;
if (y_1 <= mid)
ask(o << 1, l, mid, adv);
if (y_2 > mid)
ask(o << 1 | 1, mid + 1, r, adv);
}
int ask(int l, int r) {
if (l > r)
return INF;
y_1 = l, y_2 = r, Min = INF;
ask(1, 1, n, 0);
return Min;
}
} an[2];
int fa[mn];
int find(int x) { return !fa[x] ? x : fa[x] = find(fa[x]); }
signed main() {
freopen("product.in", "r", stdin);
freopen("product.out", "w", stdout);
in(n);
rep(q, 1, n) in(D[q]);
rep(q, 1, n) in(U[q]);
rep(q, 1, n) in(P[q]);
rep(q, 2, n) in(M[q]);
rep(q, 2, n) in(C[q]);
int sm = 0;
rep(q, 2, n) sm += C[q], an1[q] = { q, sm + P[q] };
sort(an1 + 2, an1 + n + 1);
int tp = 2;
an[0].build(1, 1, n, INF);
an[1].build(1, 1, n, 0);
long long ans = 0;
sm = 0;
rep(q, 1, n) {
an[1].add(1, q - 1, an[0].ask(q, q) > 1e9 ? M[q] : -C[q]);
sm += C[q];
an[1].change(q, U[q] ? P[q] : INF);
while (D[q]) {
while (tp <= n && (an1[tp].x <= q || !U[an1[tp].x])) ++tp;
if (tp > n || an[1].ask(1, q) <= an1[tp].v - sm) {
int v = an[1].ask(1, q);
int at = an[1].At, vl = an[0].ask(at + 1, q);
int lim = min(min(D[q], U[at]), vl);
ans += 1LL * lim * v;
while (vl == lim) {
int at1 = an[0].At;
an[1].add(1, at1 - 1, C[at1] + M[at1]);
an[0].change(at1, INF);
vl = an[0].ask(at + 1, q);
}
an[0].add(at + 1, q, -lim);
D[q] -= lim, U[at] -= lim;
if (!U[at])
an[1].change(at, INF);
} else {
int at = an1[tp].x;
int mid = at, lim = min(U[at], D[q]);
U[at] -= lim, D[q] -= lim;
while (find(mid) >= q + 1) {
an[0].change(find(mid), 0);
fa[find(mid)] = find(mid) - 1;
}
an[0].add(q + 1, at, lim);
ans += 1LL * lim * (an1[tp].v - sm);
}
}
}
printf("%lld\n", ans);
return 0;
}
「CTSC2010」产品销售的更多相关文章
- 【CTSC2010】产品销售(bzoj1920)
数据结构优化网络流…… 重新定义一下题目的各种条件: 第 $i$ 天能生产 $a_i$ 个物品: 第 $i$ 天有 $b_i$ 个物品的需求: 每存储一天物品(把订单提前一天)需要 $c_i$ 的花费 ...
- 一个「学渣」从零开始的Web前端自学之路
从 13 年专科毕业开始,一路跌跌撞撞走了很多弯路,做过餐厅服务员,进过工厂干过流水线,做过客服,干过电话销售可以说经历相当的“丰富”. 最后的机缘巧合下,走上了前端开发之路,作为一个非计算机专业且低 ...
- 把虚拟教练带回家,「EuMotus」想用AI实现高精度运动反馈系统
https://36kr.com/p/5089139.html 无需穿戴设备,只需一个红外摄像头和+已安装好EuMotus专利软件的手提电脑 由政府主导的高达2200亿美金的健身与运动支出,15%的健 ...
- 「MoreThanJava」Java发展史及起航新世界
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- 《Offer一箩筐》一份高质量「简历」撰写指南,望打扰!!
「MoreThanJava」 宣扬的是 「学习,不止 CODE」. 如果觉得 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取链接,您的支持是我前进的最大的动力! Hi~ 这里是 ...
- 「译」JUnit 5 系列:条件测试
原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Linux 小知识翻译 - 「Unix」和「兼容Unix的OS」
经常有人会问「Linux和Unix有什么区别?」,「Linux就是Unix吗?」. 回答一般都是「Linux是仿照Unix而开发的OS」,「Linux和Unix相似但不是一种OS」之类的. 关于「Li ...
- 36氪首发 | 「myShape」完成千万级人民币 Pre-A轮融资,推出 AI 智能健身私教
无需任何可穿戴设备. 36氪获悉,myShape(原Shapejoy)已于近期完成千万级人民币的Pre-A轮融资,由天奇阿米巴领投,远洋集团.七熹资本以及老股东跟投.过去 myShape 曾获得元迅资 ...
随机推荐
- 每天学一点——while循环(2)、for循环
while循环(2) while+continue 打印数字的话相信朋友们在python中不会一个个的print吧 eg: 或者是打印列表里的元素 eg 这种方法只适用于你知道里面有多少个元素, 不然 ...
- Eclipse设置代码格式化使用空格代替TAB
Java格式设置 打开Window-Preferences,找到Java-Code Style-Formatter,点击图片中的New.. 给配置起一个名字后,修改配置,找到 Indentation, ...
- Kafka和RabbitMQ有哪些区别,各自适合什么场景?
经常有人问我 有个 xx 需求,我应该用 Kafka 还是 RabbitMQ ? 这个问题很常见,而且很多人对二者的选择也把握不好. 所以我决定写篇文章来详细说一下:Kafka 和 RabbitMQ ...
- 初识python 之 smtplib 发送(dolphinscheduler任务监测)邮件
需求 监测dolphinscheduler调度系统,任务执行异常情况.如有异常,则发送邮件通知. 处理思路 因DS本身自带的邮件发送功能,不能正常发送邮件. 故而,通过查询DS源数据表,获取当前任务执 ...
- 怎样在 CentOS/RHEL 7/6 上安装和配置 Sendmail 服务器
在 CentOS 上,可以通过 mailx 命令 或 sendmail 命令来给因特网发送电子邮件. 关于前者的文章比较多,关于后者的文章比较少. 这里记录了我在 CentOS 7 上安装和配置 se ...
- spring boot 打包war后 部署到外部 tomcat 的具体正确操作【包括修改端口 与 去除请求路径的工程名】
1.前言 工程做好了,总不能放在idea运行吧?不然怎么把项目放到云服务器呢?[这一篇随笔不讲解发布的云服务器的操作,在其他随笔有详细记载.] 解决的方案是把springboot 工程 打包成war文 ...
- Echart可视化学习(十一)
文档的源代码地址,需要的下载就可以了(访问密码:7567) https://url56.ctfile.com/f/34653256-527823386-04154f 官网找到类似实例, 适当分析,并且 ...
- vue2.0多页面开发
我们平常用vue开发的时候总觉得vue好像就是专门为了单页面应用而诞生的,其实不是.因为vue在工程化开发的时候很依赖webpack,而webpack是将所有的资源整合到一块,弄成一个单页面.但是vu ...
- 【Java】final
final final可以用来修饰的结构:类.方法.变量 final 用来修饰一个类:此类不能被其他类所继承. 比如:String类.System类.StringBuffer类 final 用来修饰方 ...
- 【reverse】逆向4 初识堆栈
[reverse]逆向4 初识堆栈 1.问题引入 假设我们需要一块内存,有如下的要求 主要用于临时存储一些数据(如果数据很少可以放入寄存器中) 能够记录存了多少数据 能够非常快速的找到某个数据 2.模 ...