\(\mathcal{Description}\)

  Link.

  有 \(n\) 个位置,从左至右编号 \(1\sim n\)。在第 \(i\) 个位置放一座塔的代价为 \(c_i\),一个位置可以放任意数量的塔。给定 \(m\) 个要求,第 \(i\) 个表示 \([l_i,r_i]\) 内至少有 \(d_i\) 座塔。求最小的代价和。

  \(n\le10^3\),其余参数 \(\le10^4\)。

\(\mathcal{Solution}\)

  经历了逝量的 whk 学习,我学会了背套路。(

  原问题可以写成线规:

\[\begin{aligned}
\min~~~~&z=\sum_{i=1}^nc_i(x_i-x_{i-1})\\
\text{s.t.}~~~~&x_i\ge x_{i-1}\\
&x_{r_i}-x_{l_i-1}\ge d_i
\end{aligned},
\]

而它显然等价于:

\[\begin{aligned}
\min~~~~z'=\sum_{i=1}^n(c_i-c_{i+1})x_i+\sum_{i=1}^nI\max\{x_{i-1}-x_i,0\}+\sum_{i=1}^mI\max\{d_i-x_{r_i}+x_{l_i-1},0\}
\end{aligned}.
\]

​其中 \(I\) 是一个足够大的常数。

  我们的论文套路是,对于以下线规:

\[\min~~~~z=\sum_ub_ux_u+\sum_{\lang u,v\rang}c_{uv}\max\{0,x_v-x_u-w_{uv}\},
\]

其对应最小费用流模型:

  • \(b_u\) 表示 \(u\) 点的流出量-流入量。

    为了流量守恒,对于 \(b_u>0\) 的 \(u\),连 \(\lang S,u,b_u,0\rang\);

    对于 \(b_u<0\) 的 \(u\),连 \(\lang u,T,-b_u,0\rang\);

  • \(c_{uv}\) 表示 \(\lang u,v\rang\) 的容量,\(w_{uv}\) 表示 \(\lang u,v\rang\) 的费用,所以连边 \(\lang u,v,c_{uv},w_{uv}\rang\)。

该图的最小费用最大流的费用的相反数就是答案。

  点的系数出减入,max 外是容量,max 内是费用,减数连向被减数,最小费用相反数!


  但 whk 是落后的,我们来证明。令 \(f_{uv}\) 表示 \(\lang u,v\rang\) 的流量,考虑在上述条件下的最小费用流形式:

\[\begin{aligned}
\min~~~~&z=\sum_{\lang u,v\rang}c_{uv}f_{uv}\\
\text{s.t.}~~~~&-f_{uv}\ge-c_{uv}\\
&\sum_v f_{vu}-\sum_vf_{uv}=-b_u
\end{aligned}.
\]

令 \(p_{uv}\) 表示第一类限制的对偶,\(q_u\) 表示第二类限制的对偶,得到:

\[\begin{aligned}
\max~~~~&z=\sum_u -b_uq_u+\sum_{\lang u,v\rang}-c_{uv}p_{uv}\\
\text{s.t.}~~~~&q_v-q_u-p_{uv}\le w_{uv}
\end{aligned}.
\]

那么这个 \(p_{uv}\) 非常的自由,直接给它定成最优,所以

\[\min~~~~z=\sum_ub_uq_u+\sum_{\lang u,v\rang}c_{uv}\max\{0,q_v-q_u-w_{uv}\}
\]

的相反数就是答案。 \(\square\)

\(\mathcal{Code}\)

  总之得写势能 Dijkstra。

/*+Rainybunny+*/

#include <bits/stdc++.h>

#define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
#define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i) typedef std::pair<int, int> PII;
#define fi first
#define se second const int MAXN = 1e3, MAXM = 1e4, IINF = 0x3f3f3f3f;
int n, m, c[MAXN + 5], l[MAXM + 5], r[MAXM + 5], d[MAXM + 5]; namespace FlowGraph { const int MAXND = MAXN + 3, MAXEG = MAXN * 2 + MAXM;
int ecnt = 1, S, T, head[MAXND + 5], curh[MAXND + 5];
int hig[MAXND + 5], dis[MAXND + 5];
bool instk[MAXND + 5];
struct Edge { int to, flw, cst, nxt; } graph[MAXEG * 2 + 5]; inline void link(const int s, const int t, const int f, const int c) {
graph[++ecnt] = { t, f, c, head[s] }, head[s] = ecnt;
graph[++ecnt] = { s, 0, -c, head[t] }, head[t] = ecnt;
} inline bool spfa() {
static bool inq[MAXND + 5]; static std::queue<int> que;
rep (i, 0, T) dis[i] = IINF;
dis[S] = 0, que.push(S);
while (!que.empty()) {
int u = que.front(); que.pop(), inq[u] = false;
for (int i = head[u], v; i; i = graph[i].nxt) {
if (graph[i].flw && dis[u] + graph[i].cst < dis[v = graph[i].to]) {
dis[v] = dis[u] + graph[i].cst;
if (!inq[v]) inq[v] = true, que.push(v);
}
}
}
return dis[T] != IINF;
}
inline bool dijkstra() {
static std::priority_queue<PII, std::vector<PII>, std::greater<PII> > heap;
rep (i, 0, T) hig[i] += dis[i], dis[i] = IINF;
heap.push({ dis[S] = 0, S });
while (!heap.empty()) {
PII p(heap.top()); heap.pop();
if (dis[p.se] != p.fi) continue;
for (int i = head[p.se], v; i; i = graph[i].nxt) {
int d = p.fi + graph[i].cst + hig[p.se] - hig[v = graph[i].to];
if (graph[i].flw && dis[v] > d) heap.push({ dis[v] = d, v });
}
}
return dis[T] != IINF;
} inline PII augment(const int u, int iflw) {
if (u == T) return { iflw, 0 };
PII ret(0, 0); instk[u] = true;
for (int &i = curh[u], v; i; i = graph[i].nxt) {
if (graph[i].flw && !instk[v = graph[i].to]
&& dis[v] == dis[u] + hig[u] - hig[v] + graph[i].cst) {
PII tmp(augment(v, std::min(iflw, graph[i].flw)));
ret.fi += tmp.fi, ret.se += graph[i].cst * tmp.fi + tmp.se;
iflw -= tmp.fi, graph[i].flw -= tmp.fi, graph[i ^ 1].flw += tmp.fi;
if (!iflw) break;
}
}
if (ret.fi) instk[u] = false;
return ret;
} inline PII dinic() {
PII ret(0, 0);
for (spfa(); dijkstra(); ) {
rep (i, 0, T) curh[i] = head[i], instk[i] = false;
PII tmp(augment(S, IINF));
ret.fi += tmp.fi, ret.se += tmp.se;
}
return ret;
} } using namespace FlowGraph; int main() {
scanf("%d %d", &n, &m);
rep (i, 1, n) scanf("%d", &c[i]);
rep (i, 1, m) scanf("%d %d %d", &l[i], &r[i], &d[i]); S = n + 1, T = n + 2;
rep (i, 0, n) {
if (c[i] > c[i + 1]) link(S, i, c[i] - c[i + 1], 0);
else link(i, T, c[i + 1] - c[i], 0);
}
rep (i, 0, n - 1) link(i + 1, i, IINF, 0);
rep (i, 1, m) link(r[i], l[i] - 1, IINF, -d[i]); printf("%d\n", -dinic().se);
return 0;
}

Solution -「ZJOI 2013」「洛谷 P3337」防守战线的更多相关文章

  1. 「区间DP」「洛谷P1043」数字游戏

    「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...

  2. Solution -「JSOI 2019」「洛谷 P5334」节日庆典

    \(\mathscr{Description}\)   Link.   给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的).   \(|S|\le3\time ...

  3. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  4. Solution -「POI 2010」「洛谷 P3511」MOS-Bridges

    \(\mathcal{Description}\)   Link.(洛谷上这翻译真的一言难尽呐.   给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...

  5. Solution -「APIO 2016」「洛谷 P3643」划艇

    \(\mathcal{Description}\)   Link & 双倍经验.   给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...

  6. 「洛谷4197」「BZOJ3545」peak【线段树合并】

    题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...

  7. 「洛谷3338」「ZJOI2014」力【FFT】

    题目链接 [BZOJ] [洛谷] 题解 首先我们需要对这个式子进行化简,否则对着这么大一坨东西只能暴力... \[F_i=\sum_{j<i} \frac{q_iq_j}{(i-j)^2}-\s ...

  8. 「BZOJ2733」「洛谷3224」「HNOI2012」永无乡【线段树合并】

    题目链接 [洛谷] 题解 很明显是要用线段树合并的. 对于当前的每一个连通块都建立一个权值线段树. 权值线段树处理操作中的\(k\)大的问题. 如果需要合并,那么就线段树暴力合并,时间复杂度是\(nl ...

  9. 「洛谷3870」「TJOI2009」开关【线段树】

    题目链接 [洛谷] 题解 来做一下水题来掩饰ZJOI2019考炸的心情QwQ. 很明显可以线段树. 维护两个值,\(Lazy\)懒标记表示当前区间是否需要翻转,\(s\)表示区间还有多少灯是亮着的. ...

随机推荐

  1. 设置Linux的一些文本输出方式

    更新一下yum咯 yum install -y epel-release 火车 sudo yum install sl $ sl 放火 sudo yum install libaa-bin 小老鼠 s ...

  2. set类型转string[] 正确写法

    测试源码: 1 @org.junit.Test 2 public void testSetType(){ 3 //测试set类型转string[] 4 // 5 Set<String> s ...

  3. 二维数组与稀疏数组的转换---dataStructures

    首先我们看一个需求 在11 * 11 的五子棋的棋盘中 我们使用0代表十字交叉点也是无效的数据 用1代表黑棋 用2代表蓝棋 那么所看到的棋盘如下 改用数字显示后就如一下样式 现在我们需要将怎个棋盘存储 ...

  4. 阅读阿里Java开发手册记录

    概述 在阅读完阿里Java开发手册(嵩山版)后,发现自己在开发过程中有一些没有按照规范开发的情况,这里将容易忘记的规范记录下来,并且添加自己的理解,一方面方便自己巩固记忆,另一方面希望对其他同学能够提 ...

  5. Java常见对象内存分析

    首先要明确Java内存的个位置上放的是啥 类.对象.实例三者的关系: 1.类:是对象的模板,可以实例化对象.(this不能出现在静态方法中) 2.对象:类的个体. 3.实例:实现的对象. 4.对应的引 ...

  6. [STM32F10x] 从零开始创建一个基于标准库的工程

    硬件:STM32F103C8T6 平台:MDK-AMR V4.70 1.创建一个Keil uVision 的工程 要点:相同类型的源文件放在一起以便于管理       2.添加标准库源文件 3.添加几 ...

  7. 【刷题-PAT】A1111 Online Map (30 分)

    1111 Online Map (30 分) Input our current position and a destination, an online map can recommend sev ...

  8. golang gin框架中实现大文件的流式上传

    一般来说,通过c.Request.FormFile()获取文件的时候,所有内容都全部读到了内存.如果是个巨大的文件,则可能内存会爆掉:且,有的时候我们需要一边上传一边处理. 以下的代码实现了大文件流式 ...

  9. 学习axios必知必会(2)~axios基本使用、使用axios前必知细节、axios和实例对象区别、拦截器、取消请求

    一.axios的基本使用: ✿ 使用axios前必知细节: 1.axios 函数对象(可以作为axios(config)函数使用去发送请求,也可以作为对象调用方法axios.request(confi ...

  10. 单例模式的各种实现方式(Java)

    单例模式的基础实现方式 手写普通的单例模式要点有三个: 将构造函数私有化 利用静态变量来保存全局唯一的单例对象 使用静态方法 getInstance() 获取单例对象 懒汉模式 懒汉模式指的是单例对象 ...