• 「NOI2019d2t1」弹跳


    题目链接

    (Description)

    一个 (w imes h (1 leq w, h leq n)) 的网格上有 (n (1 leq n leq 7 imes 10 ^ 4)) 个整点;
    (m (m leq 1.5 imes 10 ^ 5)) 次连边,每次连边长度为 (t_i (1 leq t_i leq 10^4)),以第 (p_i) 个整点为起点向坐标满足 (l_i leq x leq r_i, d_i leq y leq u_i) 的所有点连边。

    (1) 号点为起点的单元最短路。

    (Sol)

    因为没有负权边,所以可以用到 (dijkstra) 的一个性质:以点 (u) 为起点松弛操作之后,到 (u) 的最短路就不会改变了。
    可以用数据结构来维护矩阵上的点,最短路时不必把边建出来,只需每次找到一个最短路最小的矩阵,并以该矩阵中未被删除的点为起点进行松弛,并把这些点删除即可。

    数据结构的选择很多,我写了线段树套 (set)

    时间复杂度 (O(nlog_2^2n)),空间复杂度 (O(n log_2 n))

    (Source)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <queue>
    int in() {
        int x = 0; char c = getchar(); bool f = 0;
        while (c < '0' || c > '9')
            f |= c == '-', c = getchar();
        while (c >= '0' && c <= '9')
            x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
        return f ? -x : x;
    }
    template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
    template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
    
    const int N = 7e4 + 5;
    
    struct city {
        int x, y;
    } a[N];
    
    struct edge {
        int p, t, l, r, d, u;
    } b[N * 3];
    
    int n, m, w, h;
    int dis[N];
    
    bool vis[N * 3];
    
    std::vector<int> s[N];
    
    typedef std::pair<int, int> pii;
    
    std::priority_queue<pii> q;
    
    std::queue<int> tmp;
    
    struct segment_tree {
        std::set<pii> t[N << 2];
    
        void insert(int id_a, int tl = 1, int tr = w, int p = 1) {
            t[p].insert(pii(a[id_a].y, id_a));
            if (tl == tr)
                return ;
            int mid = (tl + tr) >> 1;
            if (mid >= a[id_a].x)
                insert(id_a, tl, mid, p << 1);
            else
                insert(id_a, mid + 1, tr, p << 1 | 1);
        }
    
        void remove(int id_a, int tl = 1, int tr = w, int p = 1) {
            t[p].erase(pii(a[id_a].y, id_a));
            if (tl == tr)
                return ;
            int mid = (tl + tr) >> 1;
            if (mid >= a[id_a].x)
                remove(id_a, tl, mid, p << 1);
            else
                remove(id_a, mid + 1, tr, p << 1 | 1);
        }
    
        void modify(int d, int id_b, int tl = 1, int tr = w, int p = 1) {
            if (b[id_b].l <= tl && tr <= b[id_b].r) {
                std::set<pii>::iterator x = std::lower_bound(t[p].begin(), t[p].end(), pii(b[id_b].d, 0));
                for (; x != t[p].end() && x->first <= b[id_b].u; ++x) {
                    dis[x->second] = d;
                    for (unsigned i = 0; i < s[x->second].size(); ++i)
                        if (!vis[s[x->second][i]])
                            q.push(pii(-d - b[s[x->second][i]].t, s[x->second][i]));
                    tmp.push(x->second);
                }
                for (; !tmp.empty(); remove(tmp.front()), tmp.pop());
                return ;
            }
            int mid = (tl + tr) >> 1;
            if (mid >= b[id_b].l)
                modify(d, id_b, tl, mid, p << 1);
            if (mid < b[id_b].r)
                modify(d, id_b, mid + 1, tr, p << 1 | 1);
        }
    
    } T;
    
    int main() {
        //freopen("in", "r", stdin);
        n = in(), m = in(), w = in(), h = in();
        for (int i = 1; i <= n; ++i)
            a[i] = (city){in(), in()};
        for (int i = 1; i <= m; ++i) {
            b[i] = (edge){in(), in(), in(), in(), in(), in()};
            s[b[i].p].push_back(i);
        }
        for (int i = 2; i <= n; ++i)
            T.insert(i);
        for (unsigned i = 0; i < s[1].size(); ++i)
            q.push(pii(-b[s[1][i]].t, s[1][i]));
        while (!q.empty()) {
            int d = q.top().first, u = q.top().second;
            q.pop();
            if (vis[u])
                continue;
            vis[u] = 1;
            T.modify(-d, u);
        }
        for (int i = 2; i <= n; ++i)
            printf("%d
    ", dis[i]);
        return 0;
    }
    
  • 相关阅读:
    填充与复制
    张量排序
    数据统计
    合并与分割
    前向传播(张量)- 实战
    数学运算
    Broadcasting
    TensorFlow2-维度变换
    集合3
    集合2
  • 原文地址:https://www.cnblogs.com/15owzLy1-yiylcy/p/11520848.html
Copyright © 2020-2023  润新知