"Luogu5471" [NOI2019d1t1]バウンス

トピックリンク

\(アラーム内容\)

(時刻H \ W \(\ W 1 \当量、H \の当量n)は\) メッシュ上に有している\(N \(1 \当量のn \の当量7 \回10 ^ 4)\) 整数ポイント。
そこ\(Mの\(Mの\当量 1.5 \回10 ^ 5)\) 回も辺の各辺の長さであっても\(T_I \(1 \のLeq T_I \ ^ 10 1当量4)\) 最初と(\ P_I \)満たすための出発点として点を整数座標\(L_iを\当量X \当量 R_iを、\ D_I \当量Y \当量u_i \) すべてのエッジのポイントを接続します。

探している\(1 \)を最短開始部に点在。

\(ソル\)

あなたが使用できるように、否定右側はありませんので\(ダイクストラ\)自然の:ポイント\を(U \)するために、手術後のリラクゼーションのための出発点として、(uと\)\最短経路が側ではありませんです。
データ構造は、行列上の点を維持するために使用することができ、とき最短辺を構築する必要はありません、最短最小の行列を見つけるための唯一の時間、およびマトリックス内のポイントへの出発点は、リラクゼーションを削除しないように、これらのポイントを削除することができます。

多くのデータ構造を選択し、Iは、セグメントツリーセットを書きました(SET \)\

時間複雑\(O(N \ ^ log_2 2N)\) スペースの複雑\(O(N \ N-log_2)\)

\(出典\)

#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\n", dis[i]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/15owzLy1-yiylcy/p/11520848.html