zoukankan      html  css  js  c++  java
  • HDU 5361 In Touch (2015 多校6 1009 最短路 + 区间更新)

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

    题意:最短路。求源点到全部点的最短距离。但与普通最短路不同的是,给出的边是某点到区间[l,r]内随意点的距离。
    输入一个n,代表n个点,输入n个l[i],输入n个r[i],输入n个c[i]。
    对于i,表示i到区间[i - r[i]],i - l[i]]和区间[i + l[i],i + r[i]]内的随意点的距离为c[i]。


    求1到各个点的最短距离。

    思路:若建边跑最短路的话,由于边过多,所以不可行。

    由于在最后的结果中。可能源点1到某段区间的最短路径都是一样的,所以能够在最短路的算法基础上利用线段树区间更新来维护源点1到区间的最短路径,最后仅仅须要查询区间就可以。线段树的每一个结点存该区间源点到该区间点的最短路的最大值和最小值。

    所以叶子结点即是源点1到该点的最短路径。(思路来源队友)

    代码:

    #include <iostream>
    #include <iomanip>
    #include <stdio.h>
    #include <string>
    #include <string.h>
    #include <math.h>
    #include <queue>
    #include <set>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    
    const long long INF = 1e18;
    const int N = 2e5 + 10;
    
    struct Segment {
        int l, r;
        long long d;
    
        Segment(int l = 0, int r = 0, long long d = 0) {
            this -> l = l;
            this -> r = r;
            this -> d = d;
        }
    
        friend bool operator < (Segment a, Segment b) {
            return a.d > b.d;
        }
    };
    
    struct Node {
        int used;//标记该段区间是否使用过。由于距离均为正值,所以若该区间已是最短距离,则不须要继续更新。
        long long _max;
        long long _min;
    };
    
    Node node[N << 2];
    long long lazy[N << 2];
    int n;
    int lef[N];
    int rig[N];
    long long c[N];
    priority_queue<Segment> q;
    
    void pushup(int rt) {
        node[rt]._max = max(node[rt << 1]._max, node[rt << 1 | 1]._max);
        node[rt]._min = min(node[rt << 1]._min, node[rt << 1 | 1]._min);
        if (node[rt << 1].used == node[rt << 1 | 1].used)
            node[rt].used = node[rt << 1].used;
        else
            node[rt].used = -1;
    }
    
    void pushdown(int rt) {
        if (lazy[rt] != -1) {
            lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt];
            node[rt << 1]._min = node[rt << 1]._max = lazy[rt];
            node[rt << 1 | 1]._min = node[rt << 1 | 1]._max = lazy[rt];
            lazy[rt] = -1;
        }
    }
    
    void build(int l, int r, int rt) {
        node[rt]._max = INF;
        node[rt]._min = INF;
        node[rt].used = 0;
        lazy[rt] = -1;
        if (l == r) {
            if (l == 1) {
                node[rt]._max = 0;
                node[rt]._min = 0;
            }
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        pushup(rt);
    }
    
    void update(long long cr, int L, int R, int l, int r, int rt) {
        if (node[rt]._max <= cr)
            return ;
        if (L <= l && r <= R) {
            node[rt]._max = cr;
            if (node[rt]._min > cr) {
                node[rt]._min = cr;
                q.push(Segment(l, r, cr));
                lazy[rt] = cr;
                return ;
            }
        }
        if (l == r)
            return ;
        pushdown(rt);
        int m = (l + r) >> 1;
        if (L <= m)
            update(cr, L, R, lson);
        if (R > m)
            update(cr, L, R, rson);
        pushup(rt);
    }
    
    void querysegment(Segment ff, int l, int r, int rt) {
        if (node[rt].used == 1)
            return ;
        if (ff.l <= l && r <= ff.r) {
            if (node[rt].used == 0) {
                for (int i = l; i <= r; i++) {
                    int le = i + lef[i];
                    int ri = min(n, i + rig[i]);
                    if (le <= n) {
                        update(ff.d + c[i], le, ri, 1, n, 1);
                    }
                    le = max(1, i - rig[i]);
                    ri = i - lef[i];
                    if (ri >= 1) {
                        update(ff.d + c[i], le, ri, 1, n, 1);
                    }
                }
                node[rt].used = 1;
                return ;
            }
        }
        if (l == r)
            return ;
        int m = (l + r) >> 1;
        if (ff.l <= m)
            querysegment(ff, lson);
        if (ff.r > m)
            querysegment(ff, rson);
        pushup(rt);
    }
    
    bool fir;
    void query(int l, int r, int rt) {
        if (node[rt]._max == node[rt]._min) {
            for (int i = l; i <= r; i++) {
                if (node[rt]._min == INF)
                    node[rt]._min = -1;
                if (!fir) {
                    printf("%lld", node[rt]._min);
                    fir = true;
                }
                else 
                    printf(" %lld", node[rt]._min);
            }
            return ;
        }
        if (l == r) {
            return ;
        }
        pushdown(rt);
        int m = (l + r) >> 1;
        query(lson);
        query(rson);
    }
    
    int main() {
    
        int t_case;
        scanf("%d", &t_case);
        for (int i_case = 1; i_case <= t_case; i_case++) {
            scanf("%d", &n);
            for (int i = 1; i <= n; i++)
                scanf("%d", &lef[i]);
            for (int i = 1; i <= n; i++)
                scanf("%d", &rig[i]);
            for (int i = 1; i <= n; i++)
                scanf("%lld", &c[i]);
            build(1, n, 1);
            while(!q.empty())
                q.pop();
    
            q.push(Segment(1, 1, 0));
            while (!q.empty()) {
                Segment ff = q.top();
                q.pop();
                querysegment(ff, 1, n, 1);
            }
    
            fir = false;
            query(1, n, 1);
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    E语言一种特殊的找按钮事件方法
    一个后门木马的简单分析
    win32汇编学习笔记
    偶尔那么蛋疼一次
    新建springboot子模块时,pom文件project根标签会报红
    SQL Server 中用While循环替代游标(Cursor的解决方案
    修改IIS设置延长DEBUG时间
    SharePoint 201 ListViewByQuery Control 应用
    Add ContentType to pages library
    SharePoint 2010 如何取得ListItem的Attachements
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/8370725.html
Copyright © 2011-2022 走看看