题目大意

P 教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。

P 教授有编号为 \(1 \cdots n\)\(n\) 件玩具,第 \(i\) 件玩具经过压缩后的一维长度为 \(C_i\)

为了方便整理,P教授要求:

  • 在一个一维容器中的玩具编号是连续的。
  • 同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物。形式地说,如果将第 \(i\) 件玩具到第 \(j\) 个玩具放到一个容器中,那么容器的长度将为 \(x=j-i+\sum\limits_{k=i}^{j}C_k\)

制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为 \(x\),其制作费用为 \((x-L)^2\)。其中 \(L\) 是一个常量。P 教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过 \(L\)。但他希望所有容器的总费用最小。

思路

公式推导

\[ 令 f_i 表示前 i 个物品制作容器的最小费用 , sum_i = \sum_{k = 1}^{i} C_k\\ 由题意得 f_i = min\{ f_j + (i - j - 1 + sum_i - sum_j - L)^2 \ |\ j \in [1, i - 1] \}\\ 令 a_i = sum_i + i , L' = L + 1\\ \therefore f_i = f_j + (a_i - a_j - L')^2\\ 若决策j_2优于决策j_1(j_1 < j_2)\\ \therefore f_{j_1} + (a_i - a_{j_1} - L')^2 \ge f_{j_2} + (a_i - a_{j_2} - L')^2\\ \therefore 2 a_i(a_{j_2} + L') - 2 a_i(a_{j_1} + L') \ge f_{j_2} + (a_{j_2} + L')^2 - f_{j_1} - (a_{j_1} + L')^2\\ 令 b_i = f_{i} + (a_{i} + L')^2\\ \therefore 2 a_i(a_{j_2} - a_{j_1}) \ge b_{j_2} - b_{j_1}\\ \therefore 2 a_i \ge \frac{b_{j_2} - b_{j_1}}{a_{j_2} - a_{j_1}}\\ \]

做法

首先将已经决策完毕的部分按 \((a_i, b_i)​\) 画在平面直角坐标系上

在按 \(2a_i\) 与斜率的大小决定在单调队列上决策点的取舍

相当于用单调队列维护下凸包

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <bits/stdc++.h>
const int N = 50000;
const int Np = N + 5;
long long n, L, Lp, head, tail;
long long a[Np], b[Np], c[Np], f[Np], s[Np];
template <typename _Tp>
_Tp sqr(_Tp x);
template <typename _Tp>
_Tp sqr (_Tp x) { return x * x; }
int main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> n >> L;
for (int i = 1; i <= n; ++i) {
std::cin >> c[i];
a[i] = a[i - 1] + c[i] + 1;
}
Lp = L + 1;
b[0] = sqr(Lp);
head = 1;
tail = 0;
s[++tail] = 0;
for (int i = 1; i <= n; ++i) {
while (head < tail && 1.0 * ((b[s[head + 1]] - b[s[head]]) /
(a[s[head + 1]] - a[s[head]]) <= 2 * a[i] )) {
++head;
}
f[i] = f[s[head]] + sqr(a[i] - a[s[head]] - Lp);
b[i] = f[i] + sqr(a[i] + Lp);
while (head < tail && 1.0 * (b[i] - b[s[tail]]) / (a[i] - a[s[tail]]) <=
1.0 * (b[s[tail]] - b[s[tail - 1]]) / (a[s[tail]] - a[s[tail - 1]])) {
--tail;
}
s[++tail] = i;
}
std::cout << f[n] << std::endl;
return 0;
}

Day -11

  • 发现自己 比一等分数线高 \(39\)
  • 浙江 。。。
  • 赶紧报名 \(THUWC\)

Day -4

  • 自己居然过了 \(THUWC\)
  • 机房一 \(341\) 巨佬 \(PKUWC\) 没过

Day -1

  • 好紧张啊明天就要去首都了

Day 0

  • 飞机上抢到了靠窗位置
  • 紧张的一匹
  • 北京的地铁太堵了
  • 到宾馆发现先走的老师和同学们先去 \(PKU\) 报道了
  • 在宾馆等了半个小时才 发现可以直接开房间

Day 1

  • 一大早到了 \(THU\)
  • 报到送 精品围巾 ???
  • 试机 A+B ???
  • 几位巨佬教授开始讲清华有多菜 (牛)
  • 比如说 THU 计算机系被评上世界第一我们也没办法 。。。
  • 下午考试只乱七八糟拿了 \(102pts\)
  • \(20pts\) 暴力没调出来。。。
  • 看着同年级初二 skc巨佬 拿了 \(120+\) 慌的一批
  • 完了初一 wzf巨佬 都比我高
  • 回宾馆只敢睡觉了

Day 2

  • 清早就 \(Round\ 1\)
  • 一开始打了 \(T1\ 30pts\)
  • 后来一看感觉很水打了一个假 \(100\)
  • 交上去 \(Wrong\ Answer\ 0\)
  • 发现正解是假的
  • 然后加了 反正还是错的 辣鸡贪心
  • 竟然 \(70pts\) (还是只错了Subtask 1)
  • 然后和暴力整合一下就 \(A\)
  • \(30\ min\ 30pts\) 暴力没调出来。。。
  • 只有 \(100pts\)
  • 不过貌似很多人考的都没有昨天好 (我也是啊
  • 中午吃过午饭与 skc巨佬wzf巨佬 在清华园散步 (闲逛)
  • 然后吃了鸡腿匆忙赶向考场
  • \(Round\ 2\) 果然是传说中的工程题
  • \(CPU,\ Cache,\ Memory\) ???
  • 说明文档开考 \(5min\) 才发下来
  • \(A\)\(T1,\ T2\) 然后发现 \(T3\) \(CE\)
  • 开始慌,然后到最后到调不出来
  • 只有 \(96pts\)
  • \(3\) 场考试只有 \(102 + 100 + 96 = 298pts\)
  • \(300pts\) 都没到。。。
  • 看来今年凉了

Day 3

  • 不出意料没接到电话
  • 然后去天安门闲逛
  • 博物馆周一闭馆
  • 天安门、人民大会堂据说有中日韩三国领导人会议
  • 然后只能去天坛
  • 匆匆忙忙听了半个讲座就去机场了

后记

  • 感觉自己还是码力不足
  • 一堆 \(bug\)
  • 要是没有的话就多了 \(20 + 30 + 70 = 120pts\) 。。。
  • 感觉自闭了
  • 明年加油吧