W
H
X

洛谷P1442 铁球落地 题解

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;
}
posted @ 2019-12-21 23:56  -敲键盘的猫-  阅读(301)  评论(0编辑  收藏  举报