HDU5361 In Touch(线段树 + 最短路)
2016-02-24 12:56
218 查看
传送门
恰逢才做过VFK的A+B Problem,发现这道题也可以那样搞。区间连边的时候,我们就可以给那个区间在线段树对应的标号上连边。
线段树也可以不建出来,直接当做一个标号的合集,不占用内存,只用模拟在线段树上找区间的过程就可以了。
如果不清楚的话,可以看下A+B Problem的题解里面配有插图。
连好边之后就可以直接跑Dijkstra。
分析一下时间复杂度,线段树节点数是O(N)的,边数O(NlogN),所以算法复杂度为O(NlogN) 但是因为
恰逢才做过VFK的A+B Problem,发现这道题也可以那样搞。区间连边的时候,我们就可以给那个区间在线段树对应的标号上连边。
线段树也可以不建出来,直接当做一个标号的合集,不占用内存,只用模拟在线段树上找区间的过程就可以了。
如果不清楚的话,可以看下A+B Problem的题解里面配有插图。
连好边之后就可以直接跑Dijkstra。
分析一下时间复杂度,线段树节点数是O(N)的,边数O(NlogN),所以算法复杂度为O(NlogN) 但是因为
#include <cstdio> #include <cstring> #define MAXN 200005 #define MAXM 5000005 #pragma comment(linker, "/STACK:102400000,102400000") #define INF 0x3f3f3f3f3f3f3f3fLL #define I64 long long struct { int v, nxt, w; } e[MAXM << 1]; int Adj[MAXN * 6], c, n, L[MAXN], R[MAXN], N; I64 C[MAXN]; inline void Add(int u, int v, I64 w) { ++ c; e[c].v = v; e[c].nxt = Adj[u]; e[c].w = w; Adj[u] = c; } inline void GET(int &n) { static char c; n = 0; do c = getchar(); while('0' > c || c > '9'); do (n*=10)+=c-'0',c=getchar(); while('0' <= c && c <= '9'); } inline void GET(I64 &n) { static char c; n = 0; do c = getchar(); while('0' > c || c > '9'); do (n*=10)+=c-'0',c=getchar(); while('0' <= c && c <= '9'); } int LL, RR, F; void Link(int i, int l, int r) { if(LL > r || l > RR) return; if(LL <= l && r <= RR) { Add(F, n + i, C[F]); return; } int mid = (l + r) >> 1; Link(i << 1, l, mid); Link(i<<1|1, mid+1, r); } void Build(int i, int l, int r) { if(l == r) { Add(n + i, l, 0); if(i + n > N) N = i+n; return; } Add(i + n, n + (i << 1), 0); Add(n + i, n + (i << 1|1), 0); int mid = (l + r) >> 1; Build(i<<1, l, mid); Build(i<<1|1, mid+1, r); } /***************************************/ I64 dis[MAXN * 6]; int minp[MAXN * 12]; bool used[MAXN * 6]; inline void pushup(int p) { int &r = minp[p]; r = p * !used[p]; if (dis[minp[p<<1]] < dis[r]) r = minp[p<<1]; if (dis[minp[p<<1|1]] < dis[r]) r = minp[p<<1|1]; } void relax(int p, I64 d) { if(d >= dis[p]) return; dis[p] = d; for(int i = p; i; i>>=1) pushup(i); } void finish(int p) { used[p] = 1; for(int i = p; i; i>>=1) pushup(i); } /***************以上这一段可以就当做堆优化**************/ void Dijkstra() { for(int i = 0; i <= N; ++ i) dis[i] = INF, used[i] = (minp[i] = 0); relax(1, 0); while(minp[1]) { int u = minp[1]; finish(u); for(int i = Adj[u]; i; i = e[i].nxt) relax(e[i].v, dis[u] + (I64)e[i].w); } } int main() { int T; scanf("%d", &T); while(T --) { GET(n); c = N = 0; memset(Adj, 0, sizeof Adj); for(int i = 1; i <= n; ++ i) GET(L[i]); for(int i = 1; i <= n; ++ i) GET(R[i]); for(int i = 1; i <= n; ++ i) GET(C[i]); Build(1, 1, n); for(int i = 1; i <= n; ++ i) { LL = L[i]+i; RR = R[i]+i; F = i; Link(1, 1, n); RR = i-L[i]; LL = i-R[i]; Link(1, 1, n); } Dijkstra(); putchar('0'); for(int i = 2; i <= n; ++ i) printf(" %I64d", dis[i] == INF ? -1 : dis[i]); puts(""); } return 0; }
相关文章推荐
- Vector用法
- Spring Web Service 详细介绍
- android 之TCP客户端编程
- HDU5361 In Touch(线段树 + 最短路)
- 遇到mysql 5.5中文乱码问题
- 使用CocoaPods被卡住:Updating local specs repositories
- c++STL中常用模板常用函数记录(新手向)
- 237. Delete Node in a Linked List
- storm简介
- HDU——1982Kaitou Kid - The Phantom Thief (1)(坑爹string题)
- 移动互联网盈利模式
- 神经网络编程入门
- C/C++——基本数据类型的大小并且sizeof(int *) = 8
- linux设备驱动归纳总结(二):模块的相关基础概念
- 实验环境设置与使用方法
- 金融业有哪些行业----IT从业人员多了解?
- [从头学数学] 第106节 整理与复习--数学思考
- win7+ubuntu双系统中卸载ubuntu方法
- 输出整数的位数和每一位的数字
- T181 - Drive Tape Alert 7 - Media Life