LOJ 3159: "NOI2019 'bounce

Topic Portal: LOJ # 3159 .

Description meaning of the questions:

There are two-dimensional plane \ (n-\) integer-point, the coordinates of each point of the whole given \ ((x_i, y_i) \) .
There \ (m \) species edge, the \ (I \) species edge from \ (P_i \) dot even to satisfy \ (l_i \ le x_j \ le r_i \) and \ (d_i \ le y_j \ le u_i \ ) point \ (J \) , i.e., all points within a range of the rectangle.

Seeking \ (1 \) dot to the shortest length of each of the other points.

answer:

Consider Dijkstra shortest path algorithm for the process:
start only from the starting point to \ (0 \) , while others point distance is infinite.
Each taken from a point of not being updated shortest distance by which all updates have not changed since it reaches the point, and marked as having been updated.
Repeat this process until all the points are updated.

The above process is generally used to maintain the shortest distance monotonically queue points.
In this question, it may be added to the point when the next update will be many, many, and not every one will join.
You may consider adding an edge rather than points, adding this edge represents the distance of all points of this edge connected to.
Similarly, each time taken from the shortest side, when all the points inside the rectangle represented by this edge can be updated because not only to update the updated point, so that the distance of these points has been updated completely, can delete all these points.

When the above-described approach is the shortest side with "one to many", "many to many" a. Another method is to optimize the use of data structure model building side, but generally not come superior to this approach.

As to the specific point of how to maintain a rectangle delete operation, you can delete one by one violent when deleting point, because each point will only be removed once the question is how to quickly find the point you want to delete.
Here I use the tree line sets of balanced tree ( std::set) to maintain outer segment tree processing section on a horizontal axis, the inner balance of the tree can quickly access to the target point to remove it.

Here is the code, the time complexity is \ (\ mathcal {O} (n-\ ^ 2N + m log \ log m) \) :

#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>

#define mp std::make_pair
typedef std::pair<int, int> pii;
typedef std::multiset<pii>::iterator iter;
const int MN = 70005, MM = 150005;
const int MS = 1 << 18 | 7;

int N, M, W, H, yp[MN], vis[MN], dis[MN];
int h[MN], nxt[MM], et[MM], eL[MM], eR[MM], eD[MM], eU[MM];
std::multiset<pii> st[MS];
std::priority_queue<pii> pq;
void Ins(int i, int l, int r, int x, int id) {
    st[i].insert(mp(yp[id], id));
    if (l == r) return ;
    int mid = (l + r) >> 1;
    if (x <= mid) Ins(i << 1, l, mid, x, id);
    else Ins(i << 1 | 1, mid + 1, r, x, id);
}
void Del(int i, int l, int r, int id, int d) {
    if (r < eL[id] || eR[id] < l) return ;
    if (eL[id] <= l && r <= eR[id]) {
        iter it = st[i].lower_bound(mp(eD[id], 0)), tmp;
        while (it != st[i].end() && it -> first <= eU[id]) {
            int u = it -> second;
            if (!vis[u]) {
                vis[u] = 1, dis[u] = d;
                for (int j = h[u]; j; j = nxt[j])
                    pq.push(mp(-d - et[j], j));
            }
            tmp = it, ++it, st[i].erase(tmp);
        }
        return ;
    }
    int mid = (l + r) >> 1;
    Del(i << 1, l, mid, id, d);
    Del(i << 1 | 1, mid + 1, r, id, d);
}

int main() {
    freopen("jump.in", "r", stdin);
    freopen("jump.out", "w", stdout);
    scanf("%d%d%d%d", &N, &M, &W, &H);
    for (int i = 1, x; i <= N; ++i) {
        scanf("%d%d", &x, &yp[i]);
        Ins(1, 1, W, x, i);
    }
    for (int i = 1, p; i <= M; ++i) {
        scanf("%d%d%d%d%d%d", &p, &et[i], &eL[i], &eR[i], &eD[i], &eU[i]);
        nxt[i] = h[p], h[p] = i;
    }
    dis[1] = 0, vis[1] = 1;
    for (int i = h[1]; i; i = nxt[i])
        pq.push(mp(-et[i], i));
    while (!pq.empty()) {
        pii ed = pq.top(); pq.pop();
        int dis = -ed.first, id = ed.second;
        Del(1, 1, W, id, dis);
    }
    for (int i = 2; i <= N; ++i) printf("%d\n", dis[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/PinkRabbit/p/NOI2019D2T1.html