HDU 5361 In Touch(最短路 + 线段树)

来源:互联网 发布:数据交易 编辑:程序博客网 时间:2024/06/06 03:02

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5361


题意:求1点到其他点的最短路,某点在与其相差在[L, R]范围的点有连边


思路:普通的最短路经不起这么多边和状态,可以维护一颗线段树来维护当前区间的更新情况,再用优先队列去维护到下个点的最小值,用队列当前取出的点去更新区间并将被更新的点入队



#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <utility>#include <cmath>#include <queue>#include <set>#include <map>#include <climits>#include <functional>#include <deque>#include <ctime>#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int MAXN = 201000;const int MAXM = 100000;const long long INF = 1e16;typedef long long ll;int n;int L[MAXN], R[MAXN], C[MAXN];ll dis[MAXN];int tr[MAXN << 2];struct node{    int x;    node(int x = 0) : x(x) {}    bool operator < (const node &rhs) const    {        return C[x] + dis[x] > C[rhs.x] + dis[rhs.x];    }};priority_queue <node> que;void pushup(int rt){    tr[rt] = tr[rt << 1] + tr[rt << 1 | 1];}void build(int l, int r, int rt){    if (l == r)    {        tr[rt] = l == 1 ? 0 : 1;        return ;    }    int mid = (l + r) >> 1;    build(lson);    build(rson);    pushup(rt);}void update(int ql, int qr, ll c, int l, int r, int rt){    if (ql > r || qr < l) return ;    if (tr[rt] == 0) return ;    if (l == r)    {        tr[rt] = 0;        dis[l] = c;        que.push(node(l));        return ;    }    int mid = (l + r) >> 1;    if (ql <= mid)        update(ql, qr, c, lson);    if (qr > mid)        update(ql, qr, c, rson);    pushup(rt);}int main(){    int t;    cin >> t;    while (t--)    {        cin >> n;        for (int i = 1; i <= n; i++) scanf("%d", &L[i]);        for (int i = 1; i <= n; i++) scanf("%d", &R[i]);        for (int i = 1; i <= n; i++) scanf("%d", &C[i]);        for (int i = 1; i <= n; i++) dis[i] = INF;        dis[1] = 0;        que.push(node(1));        build(1, n, 1);        while (!que.empty())        {            int u = que.top().x;            que.pop();            int l = max(0, u - R[u]);            int r = max(0, u - L[u]);            if (r >= 1)                update(max(1, l), r, C[u] + dis[u], 1, n, 1);            l = min(n + 1, u + L[u]);            r = min(n + 1, u + R[u]);            if (l <= n)                update(l, min(n, r), C[u] + dis[u], 1, n, 1);        }        for (int i = 1; i <= n; i++)        {            if (dis[i] == INF) dis[i] = -1;            printf("%I64d%c", dis[i], i == n ? '\n' : ' ');        }    }    return 0;}


0 0