我崩溃了,我的做法参考了这篇题解,也就是把一次列车拆分为了开始时间的查询和结束时间的插入线段,然后对所有的时间排序并使用单调队列维护。
然后我先贴代码吧:
#include <bits/extc++.h>
#define inline __always_inline
template <typename T> inline void chkmax(T &x, const T &y) { if (x < y) x = y; }
template <typename T> inline void chkmin(T &x, const T &y) { if (x > y) x = y; }
template <typename T> inline void read(T &x)
{
char ch;
for (ch = getchar(); !isdigit(ch); ch = getchar());
for (x = 0; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
}
const int MaxN = 1e5 + 5, MaxM = 1e6 + 5, MaxOP = MaxM << 1;
const double eps = 1e-9;
int n, m, A, B, C;
int64_t f[MaxM];
struct op_t { char op; int x, t, id; } op[MaxOP];
struct line_t
{
int64_t k, b;
template <typename T> inline int64_t operator()(const T &x) { return k * x + b; }
};
std::deque<line_t> queue[MaxN];
inline double PX(const line_t &p, const line_t &q) { return 1.0 * (p.b - q.b) / (q.k - p.k); }
int main()
{
// freopen64("P6302_1.in", "r", stdin);
read(n), read(m), read(A), read(B), read(C);
int top = 1;
for (int i = 1, x, y, p, q; i <= m; i++)
read(x), read(y), read(p), read(q), op[top++] = {0, x, p, i}, op[top++] = {1, y, q, i};
std::stable_sort(op, op + top, [](const op_t &x, const op_t &y) { return x.t != y.t ? x.t < y.t : x.op > y.op; });
memset(f + 1, 0x3f, m << 3);
queue[1].push_back({0, 0});
for (int i = 1; i < top; i++)
{
int u = op[i].x, x = op[i].t, id = op[i].id;
auto &q = queue[u];
if (op[i].op == 0)
{
if (q.empty()) continue;
while (q.size() > 1 && PX(q[0], q[1]) + eps < x) q.pop_front();
chkmin(f[id], q[0](x) + (int64_t)A * x * x + (int64_t)B * x + C);
}
else
{
line_t line = {-2l * (int64_t)A * x, f[id] + (int64_t)A * x * x - (int64_t)B * x};
if (!q.empty() && line.k == q.back().k) { if (line.b >= q.back().b) continue; q.pop_back(); }
while (q.size() > 1 && PX(line, q.back()) + eps < PX(q[q.size() - 1], q[q.size() - 2])) q.pop_back();
q.push_back(line);
}
}
int64_t ans = 1e18;
for (int i = 1; i < top; i++)
if (op[i].op == 1 && op[i].x == n)
chkmin(ans, f[op[i].id] + op[i].t);
printf("%ld\n", ans);
return 0;
}
中间有一行我使用了 stable_sort,讲一讲我的调试过程:
std::sort(op, op + top, [](const op_t &x, const op_t &y) { return x.t < y.t; }); 完全没有考虑到可以绕圈磨时间这一情况,得分 58 pts.std::sort(op, op + top, [](const op_t &x, const op_t &y) { return x.t != y.t ? x.t < y.t : x.op > y.op; }); 考虑到了要先插入直线再处理查询(也就是先绕弯圈子再处理查询),但不知为何仍然 WA #1std::stable_sort(op, op + top, [](const op_t &x, const op_t &y) { return x.t != y.t ? x.t < y.t : x.op > y.op; }); 病急乱投医,把排序换成了稳定的分治排序,结果给我过了。我感觉调了一个晚上不知道在调什么,感觉应该还是离线处理的顺序错了,但不知道错哪里了。
如果大佬能够告诉我正确的排序方式,或者大佬能够 hack 我的“AC”代码,我将不胜感激,你就是我的义父
求助广大谷民!