洛谷P1442 铁球落地 题解
与这题十分类似,只是答案的计算方式有些不同,前面的部分就不说了
计算答案时上题用最短路写的,这题用dp写一遍
fl[i]表示到达每个平台左侧的最短时间,fr[i]同理
转移方程应该挺简单的,从上向下dp就行了,因为每个平台只会更新下面的两块平台,dp时间复杂度O(n),总时间复杂度nlogn
#include <bits/stdc++.h>
using namespace std;
inline void read (int &x) {
char ch = getchar(); x = 0;
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
}
const int N = 2e5 + 10;
int n, m, M, sx, sy, cnt, s[N << 1], l[N], r[N], f[N], c[N << 2], tag[N << 2], fl[N], fr[N];
struct e {
int h, l, r;
bool operator < (const e &t) {return h < t.h;}
} p[N];
inline int find (int x) {
int l (1), r (m), mid;
while (l <= r) {
mid = l + r >> 1;
if (s[mid] == x) return mid;
if (s[mid] < x) l = mid + 1;
else r = mid - 1;
}
}
#define ls p << 1
#define rs p << 1 | 1
void push_down (int p) {
if (tag[p])
c[ls] = c[rs] = tag[ls] = tag[rs] = tag[p], tag[p] = 0;
}
void update (int p, int l, int r, int ql, int qr, int val) {
if (ql <= l && qr >= r) {c[p] = tag[p] = val; return;}
push_down (p);
int mid (l + r >> 1);
if (ql <= mid) update (ls, l, mid, ql, qr, val);
if (qr > mid) update (rs, mid + 1, r, ql, qr, val);
}
int query (int p, int l, int r, int pos) {
if (l == r) return c[p];
push_down (p);
int mid (l + r >> 1);
return pos <= mid ? query (ls, l, mid, pos) : query (rs, mid + 1, r, pos);
}
inline int Min (int a, int b) {return a > b ? b : a;}
signed main() {
read (n), read (M), read (sx), read (sy);
for (int i = 1; i <= n; ++i) read (p[i].h), read (p[i].l), read (p[i].r);
sort (p + 1, p + n + 1);
while (p[n].h >= sy) --n;
p[++n] = (e) {sy, sx, sx};
for (int i = 1; i <= n; ++i) s[++cnt] = p[i].l, s[++cnt] = p[i].r;
sort (s + 1, s + cnt + 1); m = 1;
for (int i = 2; i <= cnt; ++i) if (s[i] != s[i - 1]) s[++m] = s[i];
for (int i = 1; i <= n; ++i) p[i].l = find (p[i].l), p[i].r = find (p[i].r);
// for (int i = 1; i <= n; ++i) printf ("%d %d\n", p[i].l, p[i].r);
for (int i = 1; i <= n; ++i) {
l[i] = query (1, 1, m, p[i].l), r[i] = query (1, 1, m, p[i].r);
update (1, 1, m, p[i].l, p[i].r, i);
}
// for (int i = 1; i <= n; ++i) printf ("%d %d %d %d %d\n", p[i].h, p[i].l, p[i].r, l[i], r[i]);
memset (fl, 0x3f, sizeof (fl));
memset (fr, 0x3f, sizeof (fr));
fl[n] = fr[n] = 0;
for (int i = n; i >= 1; --i) {
if (p[i].h - p[l[i]].h <= M) {
int t1 (0), t2 (0);
if (l[i]) t1 = s[p[i].l] - s[p[l[i]].l], t2 = s[p[l[i]].r] - s[p[i].l];
fl[l[i]] = Min (fl[l[i]], 1ll * fl[i] + p[i].h - p[l[i]].h + t1);
fr[l[i]] = Min (fr[l[i]], 1ll * fl[i] + p[i].h - p[l[i]].h + t2);
}
if (p[i].h - p[r[i]].h <= M) {
int t1 (0), t2 (0);
if (r[i]) t1 = s[p[i].r] - s[p[r[i]].l], t2 = s[p[r[i]].r] - s[p[i].r];
fl[r[i]] = Min (fl[r[i]], 1ll * fr[i] + p[i].h - p[r[i]].h + t1);
fr[r[i]] = Min (fr[r[i]], 1ll * fr[i] + p[i].h - p[r[i]].h + t2);
}
}
// for (int i = n; i >= 0; --i) printf ("%d %d\n", fl[i], fr[i]);
printf ("%d", Min (fl[0], fr[0]));
return 0;
}