1 条题解
-
11
闲话
当我往代码的某个位置加上了一个
=
号后,我的代码的内存占用缩小至了原来的 。我并没有开玩笑。同时,运行效率也提高了不知道多少倍,因为没加等号的程序运行第 个样例时需要占用 10G+ 的内存,而我的电脑是撑不住的,所以我把它 Ctrl-C 了,不知道实际运行时间。而加了等号之后,所有样例运行时间都未超过 毫秒。题解
考虑如下算法:
假设目前走到了位置 。从位置 到位置 有若干种可能的方案,其中每种方案可以使用二元组 表示。其中, 代表走到这个位置的总用时,而 代表目前行进 个单位长度所用的时间。
我们称一个二元组集合 是精悍的,当且仅当该集合内任意两个相异二元组 和 不满足 。
定义一次清理为将一个二元组集合 转换为它的一个精悍的子集 ,并且在其中 的最小值尽可能小的前提下 尽可能大。
定义一次距离为 的步进为将一个二元组集合 内的每个元素 转换为 。
定义一次参数为 的可能加油为设集合 为集合 的一对一映射 ,令 。
将可能加油和询问统称为事件。
初始时,令 为 。第一个元素为初始状态,第二个元素为不加油的边界条件。
接下来,将询问与加油站放在一起排序,令新的位置数组为 ,大小为 。令 ,则依次对于第 个事件,执行一次距离为 的步进,并进行清理。接下来,若该事件为询问,则答案为 中所有元素中最小的 值。否则执行一次参数为 的可能加油,并进行清理。
我无法分析上述做法的准确时间复杂度,但上述方法确实可以通过此题。
代码
#include <algorithm> #include <cctype> #include <cstdio> #include <list> using namespace std; const int N = 2e5 + 10, inf = 1e9; using ld = long double; const ld eps = 1e-7; template <typename _Tp> inline void read(_Tp &x) { char ch; while (ch = getchar(), !isdigit(ch)) ; x = (ch ^ 48); while (ch = getchar(), isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48); } template <typename _Tp, typename... _Args> inline void read(_Tp &x, _Args &...args) { read(x); read(args...); } struct st { ld ctm, spd; bool operator<(const st &x) const { if (ctm != x.ctm) return ctm > x.ctm; return spd < x.spd; } }; struct evrt { int p, t, x; bool operator<(const evrt &tx) const { if (p != tx.p) return p < tx.p; if (t != tx.t) return t < tx.t; return x < tx.x; } } evnt[N]; list<st> curwk, buf; int n, m, cur; ld res[N]; void clr() { curwk.sort(); for (auto &i : curwk) { while (buf.size() and buf.back().spd >= i.spd) buf.pop_back(); buf.emplace_back(i); } curwk.swap(buf); buf.clear(); } void frwd(int x) { cur += x; for (auto &i : curwk) { i.ctm += i.spd * x; } clr(); } void charge(evrt a) { // if (a.x == 1) // return; int tmp = curwk.size(); auto it = curwk.begin(); for (int i = 0; i < tmp; i++) { curwk.emplace_back(st{it->ctm + a.t, it->spd / a.x}); if (curwk.back().spd * (inf - cur) < eps) curwk.back().spd = 0; it++; } clr(); } int main() { freopen("ship.in", "r", stdin); freopen("ship.out", "w", stdout); read(n, m); curwk.emplace_back(st{0, 1}); curwk.emplace_back(st{1e9, 0}); for (int i = 1; i <= n; i++) { read(evnt[i].p, evnt[i].t, evnt[i].x); } for (int i = 1; i <= m; i++) { read(evnt[i + n].p); evnt[i + n].t = -1; evnt[i + n].x = i; } sort(evnt + 1, evnt + n + m + 1); for (int i = 1; i <= n + m; i++) { if (cur != evnt[i].p) frwd(evnt[i].p - cur); if (~evnt[i].t) { charge(evnt[i]); continue; } res[evnt[i].x] = curwk.back().ctm; } for (int i = 1; i <= m; i++) { printf("%.7Lf\n", res[i]); } }
- 1
信息
- ID
- 94
- 时间
- 3000ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 804
- 已通过
- 174
- 上传者