LOJ 3159 : "NOI2019 '바운스

주제 포털 : LOJ 번호 3159 .

질문에 대한 설명의 의미 :

2 차원 평면에있다 \ (\ N-) 정수 점, 주어진 전체의 각 점의 좌표 (\ (x_i로부터, y_i) \) .
거기 \ (m의 \) 종 에지는 \ (I는 \) 의 종 에지 \ (P_i는 \) 을 만족하도록하더라도 도트 \을 (l_i \ 르 x_j \ 르 r_i \) 와 \ (d_i \ 르 y_j \ 르 u_i \ ) 포인트 \ (J \) , 즉 직사각형의 범위 내의 모든 포인트.

상대 \ (1 \)를 다른 포인트들 각각의 최단 길이 도트.

해결 방법 :

프로세스를위한 다 익스트라 알고리즘은 최단 경로를 고려
하기 만 시작점에서 시작 \ (0 \)를 , 다른 거리가 무한대 가리키고있다.
각각의 모든 업데이트가 업데이트 된 것으로 그 지점에 도달 이후에 변경하고, 표시하지 아니하는 업데이트되는 최단 거리의 시점에서 촬영.
모든 포인트가 업데이트 될 때까지이 과정을 반복합니다.

상기 방법은 일반적으로 단조롭게 큐 포인트의 최단 거리를 유지하기 위해 사용된다.
이 질문에서는, 다음 업데이트는, 많은 많은 것 때 지점에 추가 할 수 있습니다, 그리고 모든 사람이 참여합니다.
이 가장자리를 추가하면 연결이 가장자리의 모든 지점의 거리를 나타내며, 포인트보다는 가장자리를 추가하는 것도 고려해 볼 수 있습니다.
유사하게, 각 시간은, 이러한 점의 거리가 완전하게 업데이트되어 있도록 업데이트 지점을 업데이트 할뿐만 아니라,이 때문에 에지가 나타내는 사각형 내부의 모든 포인트가 업데이트 될 수있는 짧은 측면 수로 찍은 이러한 모든 점을 삭제합니다.

전술 한 방법은 "대다" "한 많은 행"과 짧은 측면 인 경우. 또 다른 방법은 데이터 구조의 모형 구축 측의 사용을 최적화 할 수 있지만, 일반적으로 이러한 접근 우수한 오지.

각 지점은 제거되기 때문에 문제는 신속하게 삭제하려는 지점을 찾는 방법되면 사각형은 삭제 작업을 유지하는 방법의 특정 지점에 관해서는, 당신은 하나 삭제할 때 폭력 포인트를 삭제할 수 있습니다.
여기서 I는 균형 트리 (의 트리 라인의 세트를 사용하여 std::set가로 축에 외부 세그먼트 트리 처리부를 유지), 빨리 목표 지점에 접근 할 수있는 트리의 내부 밸런스는 제거한다.

다음 코드는 시간 복잡도가된다 (\ \ mathcal {O} (N- \ ^ 2N + m 로그 \ 로그 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;
}

추천

출처www.cnblogs.com/PinkRabbit/p/NOI2019D2T1.html