• 洛谷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
    ", 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
    ", 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
    ", fl[i], fr[i]);
        printf ("%d", Min (fl[0], fr[0]));
        return 0;
    }
    
  • 相关阅读:
    CodeForces 697B Barnicle 模拟
    15.三数之和
    167.两数之和
    209.长度最小子数组-sliding window
    COMP9313 Week9a-0
    树总纲(To be continued)
    COMP9517 Week8
    COMP9313 week8b Pipeline
    94. 二叉树的中序遍历
    COMP9313 Week8 Classification and PySpark MLlib
  • 原文地址:https://www.cnblogs.com/whx666/p/12078745.html
Copyright © 2020-2023  润新知