「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」产品销售的更多相关文章

  1. 【CTSC2010】产品销售(bzoj1920)

    数据结构优化网络流…… 重新定义一下题目的各种条件: 第 $i$ 天能生产 $a_i$ 个物品: 第 $i$ 天有 $b_i$ 个物品的需求: 每存储一天物品(把订单提前一天)需要 $c_i$ 的花费 ...

  2. 一个「学渣」从零开始的Web前端自学之路

    从 13 年专科毕业开始,一路跌跌撞撞走了很多弯路,做过餐厅服务员,进过工厂干过流水线,做过客服,干过电话销售可以说经历相当的“丰富”. 最后的机缘巧合下,走上了前端开发之路,作为一个非计算机专业且低 ...

  3. 把虚拟教练带回家,「EuMotus」想用AI实现高精度运动反馈系统

    https://36kr.com/p/5089139.html 无需穿戴设备,只需一个红外摄像头和+已安装好EuMotus专利软件的手提电脑 由政府主导的高达2200亿美金的健身与运动支出,15%的健 ...

  4. 「MoreThanJava」Java发展史及起航新世界

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...

  5. 《Offer一箩筐》一份高质量「简历」撰写指南,望打扰!!

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」. 如果觉得 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取链接,您的支持是我前进的最大的动力! Hi~ 这里是 ...

  6. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  7. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  8. Linux 小知识翻译 - 「Unix」和「兼容Unix的OS」

    经常有人会问「Linux和Unix有什么区别?」,「Linux就是Unix吗?」. 回答一般都是「Linux是仿照Unix而开发的OS」,「Linux和Unix相似但不是一种OS」之类的. 关于「Li ...

  9. 36氪首发 | 「myShape」完成千万级人民币 Pre-A轮融资,推出 AI 智能健身私教

    无需任何可穿戴设备. 36氪获悉,myShape(原Shapejoy)已于近期完成千万级人民币的Pre-A轮融资,由天奇阿米巴领投,远洋集团.七熹资本以及老股东跟投.过去 myShape 曾获得元迅资 ...

随机推荐

  1. Vue总结第六天:Vuex (全局变量管理~多个页面共享数据)

    Vue总结第六天:Vuex (全局变量管理~多个页面共享数据) 目录 一.Vuex (全局变量管理~~多个页面共享数据) ✿ 更详细的可以看官网:开始 | Vuex 1.什么是Vuex? 2.核心概念 ...

  2. 【死磕Java并发】-----Java内存模型之重排序

    在执行程序时,为了提供性能,处理器和编译器常常会对指令进行重排序,但是不能随意重排序,不是你想怎么排序就怎么排序,它需要满足以下两个条件: 在单线程环境下不能改变程序运行的结果: 存在数据依赖关系的不 ...

  3. mod4最优路径问题(转载)

    原文链接:https://blog.csdn.net/ACdreamers/article/details/18501855 mod4最优路径问题 如下图: 从1到4找出一条路径,要求路径的总长度mo ...

  4. 【算法】main函数的堆栈溢出

    main函数的堆栈的大小默认为1mb 如果把数组int x[1000][1000]定义在main函数里 则int为4byte,8bit为1byte,1024byte为1kb,1024kb为1mb 4* ...

  5. Java面向对象程序设计作业目录(作业笔记)

    持续更新中............. 我的大学笔记>>> 第1章 面向对象 >>> 1.1.5 编写Java程序,创建Dota游戏中的防御塔类,通过两个坐属性显示防 ...

  6. 把rocksdb配置成leveldb

    将rocksdb配置成leveldb 1.配置方法 配置方式有三种: 第一种适合进行性能测试对比:是以参数形式在运行db_bench或ycsb-c的时候以参数形式将rocksdb将其配置成leveld ...

  7. Centos7 安装 brctl 工具

    [root@docker-node1 ~]# brctl show -bash: brctl: command not found [root@docker-node1 ~]# yum -y inst ...

  8. 用软碟通UltraISO刻录Win 10 1909 到U盘,只有1个G左右,安装不了系统

    之前一直用软碟通刻录WIN10的ISO镜像到U盘.最近想到用最新版的WIN10 1909 来做一个U盘系统,刻录也成功了.就是安装系统的时候总报错,找了很久原因,终于发现刻录后占用U盘的空间只有1G左 ...

  9. 第10组 Alpha冲刺 (3/6)(组长)

    1.1基本情况 ·队名:今晚不睡觉 ·组长博客:https://www.cnblogs.com/cpandbb/p/13971668.html ·作业博客:https://edu.cnblogs.co ...

  10. Word2010制作倒福字

    原文: https://www.toutiao.com/i6489772955797553677/ 选择"插入"选项卡,"插图"功能组,"形状&quo ...