【凸壳】luogu_P7249 Minimum Cost Paths P
题意
在一个 \(N \times M\) 的方格图上。
在\((x,y)\),有两种移动方式:
- 可以以 \(x^2\) 的代价向右移动。
- 可以以 \(c_y\) 的代价向下移动。
对于\(Q\)个询问,求出从 \((1,1)\) 到 \((x,y)\) 的最小代价。
\(100 \%, 2≤N≤10^9,2≤Q,M≤2 \times 10^5\)
思路
设想答案是一条 \((1,1)\) 到 \((1,y)\) 的直线选择若干个转折点向下折到 \((x,y)\) 。
假设当前点为 \((x,y)\) ,要走到 \((n,m)\) ,那么向下折一下的代价为 \(c_y+(m-y)(2x+1)\) ,后面这一段是根据完全平方公式算出向右走要加上的代价。
拆开这个式子,得 \(c_y+2xm+m-2xy-y\),将关于 \(x\) 的常数项扔掉,得到了一个关于 \(x\) 的函数 \(c_y-2xy-y\)。
对于 \(x\) ,选择一个 \(y\) 向下折使得代价最小,即可最小化答案。
然而我们只能向右走不能向左走,这就要求选出的y是递增的。观察 \(c_y-2xy-y\) ,发现\(-2y\)是随着 \(y\) 递增而递减的。
而最小化这个式子,需要维护一个下凸壳,这样子对于递增的\(x\),\(-2y\)是递减的,保证了\(y\)是递增的。
那么直接做即可。
代码
#include <cmath>
#include <cstdio>
#include <algorithm>
#define int long long
struct node {
int x, y, id;
} que[200001];
int n, m, q, top;
int k[200001], b[200001], s[200001], sum[200001], l[200001], r[200001], ans[200001];
int cmp(node x, node y) {
return x.y < y.y;
}
int cross(int i, int j) {
return ceil((double)(b[j] - b[i]) / (k[i] - k[j]));
}
int calc(int i, int l, int r) {
return (k[i] * (l + r) + 2 * b[i]) / 2 * (r - l + 1);//woshishabi:!!!
}
signed main() {
scanf("%lld %lld", &n, &m);
for (int i = 1; i <= m; i++)
scanf("%lld", &b[i]), b[i] -= i, k[i] = -2 * i;
scanf("%lld", &q);
for (int i = 1; i <= q; i++)
scanf("%lld %lld", &que[i].x, &que[i].y), que[i].id = i;
std::sort(que + 1, que + q + 1, cmp);
for (int i = 1, pt = 1; i <= m; i++) {
while (top && cross(i, s[top]) <= l[s[top]])
top--;//维护单调性
l[i] = top ? cross(i, s[top]) : 1;
r[i] = n;
if (l[i] <= r[i]) {//更新一系列值
r[s[top]] = l[i] - 1;
if (top)
sum[top] = sum[top - 1] + calc(s[top], l[s[top]], r[s[top]]);
s[++top] = i;
sum[top] = sum[top - 1] + calc(i, l[i], r[i]);
}
while (que[pt].y == i && pt <= q) {//求答案
int qx = que[pt].x - 1, ll = 1, rr = top;
while (ll < rr) {
int mid = ll + rr >> 1;
if (qx <= r[s[mid]])
rr = mid;
else
ll = mid + 1;
}
ans[que[pt].id] = sum[ll - 1] + calc(s[ll], l[s[ll]], qx) + qx * i * (2 + qx) + i - 1;//横着走的代价最后算即可
pt++;
}
}
for (int i = 1; i <= q; i++)
printf("%lld\n", ans[i]);
}
巨大坑点
又犯下了先×后➗的滔天大罪!

浙公网安备 33010602011771号