「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 曾获得元迅资 ...
随机推荐
- Rainbond通过插件整合ELK/EFK,实现日志收集
前言 ELK 是三个开源项目的首字母缩写:Elasticsearch.Logstash 和 Kibana.但后来出现的 FileBeat 可以完全替代 Logstash的数据收集功能,也比较轻量级.本 ...
- Propensity Scores
目录 基本的概念 重要的结果 应用 Propensity Score Matching Stratification on the Propensity Score Inverse Probabili ...
- matplotlb 进阶之Styling with cycler
目录 cycler 教程 函数链接 matplotlib教程学习笔记 cycler 在教程开始之前,我们需要了解cycler模块 from __future__ import print_functi ...
- 利用数学软件Mathematica的三维图像进行建模
前言 最近在使用Mathematica进行二元函数的图像绘制,在导出图像选项中看到了obj,maya等三维格式.其实很早之前我就有过这样的想法,但之前使用的是matlab作图,无法导出三维格式.那么废 ...
- Java面向对象笔记 • 【第3章 继承与多态】
全部章节 >>>> 本章目录 3.1 包 3.1.1 自定义包 3.1.2 包的导入 3.1.3 包的访问权限 3.1.4 实践练习 3.2 继承 3.2.1 继承概述 3 ...
- getRequestDispatcher 中请求转发和请求包含的使用说明
getRequestDispatcher() getRequestDispatcher() 包含两个方法,分别是请求转发和请求包含. RequestDispatcher rd = request.ge ...
- 龙芯发布.NET 6.0.100开发者试用版
龙芯在龙芯开源社区发布了LoongArch64-.NET-SDK-6.0.100开发者试用版 新闻 ,龙芯.NET基于上游社区 版本 适配支持龙芯平台架构. 目前支持LoongArch64架构和MIP ...
- pip list 精确查找某一模块的方法
1. 今天搜资料的时候get一项技能: pip list精确查找某一模块 命令如下: pip list | findstr "win32" (此处win32可以替换成任意想查找的模 ...
- 由浅入深学习Apache httpd原理与配置
一.apache简介: Apache HTTPD又可以简称为httpd或者Apache,它是Internet使用最广泛的web服务器之一,使用Apache提供的web服务器是由守护进程httpd,通过 ...
- python中addict模块,设置和读取嵌套字典
源码地址: https://github.com/mewwts/addict/blob/master/README.md