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("\n");
    }
    return 0;
}HDU 5361 In Touch (2015 多校6 1009 最短路 + 区间更新)的更多相关文章
- Hdu 5361  In Touch (dijkatrs+优先队列)
		
题目链接: Hdu 5361 In Touch 题目描述: 有n个传送机排成一排,编号从1到n,每个传送机都可以把自己位置的东西传送到距离自己[l, r]距离的位置,并且花费c,问从1号传送机到其他 ...
 - HDU 4704 Sum (2013多校10,1009题)
		
Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submi ...
 - HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)
		
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...
 - hdu 1556:Color the ball(第二类树状数组 —— 区间更新,点求和)
		
Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
 - 2015 Multi-University Training Contest 6 hdu 5361 In Touch
		
In Touch Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total ...
 - HDU 5301 Buildings(2015多校第二场)
		
Buildings Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Tota ...
 - hdu 5317 RGCDQ (2015多校第三场第2题)素数打表+前缀和相减求后缀(DP)
		
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5317 题意:F(x) 表示x的不同质因子的个数结果是求L,R区间中最大的gcd( F(i) , F(j ...
 - hdu 5316 Magician(2015多校第三场第1题)线段树单点更新+区间合并
		
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5316 题意:给你n个点,m个操作,每次操作有3个整数t,a,b,t表示操作类型,当t=1时讲a点的值改 ...
 - hdu 5305 Friends(2015多校第二场第6题)记忆化搜索
		
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5305 题意:给你n个人,m条关系,关系可以是online也可以是offline,让你求在保证所有人on ...
 
随机推荐
- 【MPI】并行求和
			
比较简单的并行求和 读入还是串行的 而且无法处理线程数无法整除数据总长度的情况 主要用到了MPI_Bcast MPI_Scatter MPI_Reduce typedef long long __in ...
 - Spring整合Mybatis案例,献给初学的朋友
			
今天我们来学习Spring整合Mybatis. 开发环境:Ide:MyEclipse 2017 CI JDK:1.8 首先我们简单的认识下这两个框架 1.Mybatis MyBatis是一个支持普通S ...
 - [转载]for循环的执行顺序
			
原文地址:for循环的执行顺序作者:想飞上天的美人鱼 for循环的执行顺序用如下表达式: for(expression1;expression2;expression3) { expression ...
 - 【java失业择业中】失业第四天:准备面试
			
1.jQuery基础 学好jquery的一个基础条件是学好css层叠样式,因为很多时候这2个是一块配合使用的. 页面中很多需要jquery实现的效果只是通过jquery的选择器,选中要操作的元素,添加 ...
 - 使用vue脚手架工具搭建vue-webpack项目
			
对于Vue.js来说,如果你想要快速开始,那么只需要在你的html中引入一个<script>标签,加上CDN的地址即可.但是,这并不算是一个完整的vue实际应用.在实际应用中,我们必须要一 ...
 - /etc/fstab格式的问题
			
[root@localhost etc]# cat fstab /dev/VolGroup00/LogVol00 / ext3 defaults ...
 - HTTP和HTTPS的区别,以及各自的优缺点
			
转自 https://www.cnblogs.com/wqhwe/p/5407468.html 超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容 ...
 - Hibernate:不容易理解的 lock 和 merge
			
背景 lock 和 merge 在字面上很容易理解它们的语义,不过它们的实际行为所代表的语义范围要大一点,本文就简单的记录下来,还请朋友们多批评和指正. Lock 官方的注释 /** * Obtain ...
 - MERGE新特性(UPDATE WHERE,DELETE WHERE,INSERT WHERE)
			
MERGE语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句.通过MERGE语句,根据一张表或子查询的连接条件对另外一张表进行查询,连接条件匹配上的进行UPDATE,无法匹配的执 ...
 - 斯坦福大学卷积神经网络教程UFLDL Tutorial - Convolutional Neural Network
			
Convolutional Neural Network Overview A Convolutional Neural Network (CNN) is comprised of one or mo ...