今年D1T1,平心而论,如果能想到kruskal重构树还是很简单的。

......苟屁啊!虽然跟其他的比是简单些,但是思维难度中上,代码难度中上,怎么看都很符合NOI T1啊。

本题还有可持久化并查集的做法,以高度为版本。我没有打......

言归正传,来看题。

给你一个无向图,每条边有高度和长度。每次询问,从点s出发,只能经过高度大于h的边所能到达的点中,距1号点最近的点的距离。强制在线。

n<=200000,m<=400000,q<=400000

首先,离线有65分,十分可观。我们把边和询问都按照高度排序。然后依次加入,并查集维护连通块内dis最小值。

克鲁斯卡尔重构树解法:

首先讲什么是克鲁斯卡尔重构树:说起来也蛮简单,就是你把边排序,加边的时候如果连通就不加,否则新建节点代表这个连通块,边的两端所在连通块的代表节点作为这个新节点的两个子节点。

这样你要查询高度h时dis min,只需维护一个节点所代表连通块内dis最小值即可。每次向上跳,可以发现一条链上的dis min单调不增。然后就倍增了,类似lca。

啊我到底在口胡什么。

 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue> const int N = , INF = 0x7f7f7f7f; struct Edge_1 {
int v, len, nex;
}edge_1[N << ]; int top_1; // for dijkstra struct POI {
int id, dis;
inline bool operator <(const POI &d) const {
return dis > d.dis;
}
POI(int a, int b) {
id = a;
dis = b;
}
}; // for dijkstra struct Edge_2 {
int u, v, h;
inline bool operator <(const Edge_2 &d) const {
return h > d.h;
}
}edge_2[N << ]; int top_2; // for sort kruskal struct UFS {
int fa[N * ];
inline void clear() {
for(int i = ; i < N * ; i++) {
fa[i] = i;
}
return;
}
UFS() {
clear();
}
int find(int x) {
if(fa[x] == x) {
return x;
}
return fa[x] = find(fa[x]);
}
inline void merge(int x, int y) { // x <- y
fa[find(y)] = find(x);
return;
}
}ufs; int e[N], dis[N * ]; // for dijkstra
int fa[N * ][], tot, h[N * ]; // for kruskal inline void add_1(int x, int y, int z) {
top_1++;
edge_1[top_1].v = y;
edge_1[top_1].len = z;
edge_1[top_1].nex = e[x];
e[x] = top_1;
return;
} inline void add_2(int x, int y, int z) {
top_2++;
edge_2[top_2].u = x;
edge_2[top_2].v = y;
edge_2[top_2].h = z;
return;
} inline void clear() {
top_1 = ;
top_2 = ;
memset(e, , sizeof(e));
ufs.clear();
return;
} inline void dijkstra() {
std::priority_queue<POI> Q;
memset(dis, 0x3f, sizeof(dis));
dis[] = ;
Q.push(POI(, )); // POI(id, dis)
while(!Q.empty()) {
while(!Q.empty() && dis[Q.top().id] != Q.top().dis) {
Q.pop();
}
if(Q.empty()) {
break;
}
int x = Q.top().id;
Q.pop();
for(int i = e[x]; i; i = edge_1[i].nex) {
int y = edge_1[i].v;
if(dis[y] > dis[x] + edge_1[i].len) {
dis[y] = dis[x] + edge_1[i].len;
Q.push(POI(y, dis[y]));
}
}
}
return;
} inline void add(int p) {
int x = ufs.find(edge_2[p].u);
int y = ufs.find(edge_2[p].v);
if(x == y) {
return;
}
++tot;
fa[x][] = tot;
fa[y][] = tot;
ufs.merge(tot, x);
ufs.merge(tot, y);
h[tot] = edge_2[p].h;
dis[tot] = std::min(dis[x], dis[y]);
return;
} inline int solve(int x, int high) {
int t = ;
while(t >= ) {
if(h[fa[x][t]] > high) {
x = fa[x][t];
}
t--;
}
return dis[x];
} int main() {
int T;
scanf("%d", &T);
while(T--) {
int n, m;
scanf("%d%d", &n, &m);
tot = n;
h[] = -;
for(int i = , x, y, z, w; i <= m; i++) {
scanf("%d%d%d%d", &x, &y, &z, &w);
add_1(x, y, z);
add_1(y, x, z);
add_2(x, y, w);
} // prework
dijkstra();
std::sort(edge_2 + , edge_2 + m + );
for(int i = ; i <= m; i++) {
add(i);
}
for(int i = ; i <= ; i++) {
for(int x = ; x <= tot; x++) {
fa[x][i] = fa[fa[x][i - ]][i - ];
}
} int q, k, s, op, high, la = ;
scanf("%d%d%d", &q, &k, &s);
while(q--) {
scanf("%d%d", &op, &high);
op = (op + k * la - ) % n + ;
high = (high + k * la) % (s + );
la = solve(op, high);
printf("%d\n", la);
}
clear();
}
return ;
}

AC代码

170行代码还行。

[NOI2018]归程的更多相关文章

  1. [NOI2018]归程 kruskal重构树

    [NOI2018]归程 LG传送门 kruskal重构树模板题. 另一篇文章里有关于kruskal重构树更详细的介绍和更板子的题目. 题意懒得说了,这题的关键在于快速找出从查询的点出发能到达的点(即经 ...

  2. [洛谷P4768] [NOI2018]归程 (kruskal重构树模板讲解)

    洛谷题目链接:[NOI2018]归程 因为题面复制过来有点炸格式,所以要看题目就点一下链接吧\(qwq\) 题意: 在一张无向图上,每一条边都有一个长度和海拔高度,小\(Y\)的家在\(1\)节点,并 ...

  3. NOI2018 D1T1 [NOI2018]归程 解题报告

    P4768 [NOI2018]归程 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 \(n\) 个节点.\(m\) 条边的无向连通图(节点的编号从 \ ...

  4. BZOJ_5415_[Noi2018]归程_kruscal重构树+倍增+最短路

    BZOJ_5415_[Noi2018]归程_kruscal重构树+倍增 Description www.lydsy.com/JudgeOnline/upload/noi2018day1.pdf 好久不 ...

  5. 题解 NOI2018 归程

    题解 NOI2018 归程 题意 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l, ...

  6. [NOI2018]归程(kruscal重构树)

    [NOI2018]归程 题面太长辣,戳这里 模拟赛上写了一个spfa (关于spfa,它已经死了),然后一个st表水完暴力跑路.考后说是Kruscal重构树或者可持久化并查集???这都是些什么东西.不 ...

  7. [luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树)

    [luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树) 题面 题面较长,这里就不贴了 分析 看到不能经过有积水的边,即不能经过边权小于一定值的边,我们想到了kru ...

  8. Luogu P4768 [NOI2018]归程(Dijkstra+Kruskal重构树)

    P4768 [NOI2018]归程 题面 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 \(n\) 个节点. \(m\) 条边的无向连通图(节点的编 ...

  9. P4768 [NOI2018]归程(kruskal 重构树)

    洛谷P4768 [NOI2018]归程 LOJ#2718.「NOI2018」归程 用到 kruskal 重构树,所以先说这是个啥 显然,这和 kruskal 算法有关系 (废话 这个重构树是一个有点权 ...

  10. BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra

    题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l,a 描述一条边的长度.海 ...

随机推荐

  1. zepto的extend

    类型判断 var class2type = {},toString = class2type.toString,$={}; //判断类型 function type(obj) { return obj ...

  2. 用mescroll实现无限上拉增加数据,下拉刷新数据 (学习笔记)

    最近自己做一个web app需要用到上拉查询下页数据,网上看了很多很多帖子,发现并不能快速的套用,总是会出现各种问题无法使用,于是无奈自己跑去看了官方api文档,终于做了出来,至此做个笔记,以后用到可 ...

  3. @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})

    @EnableAutoConfiguration 作用:Spring Boot会自动根据你jar包的依赖来自动配置项目. 例如当你项目下面有HSQLDB的依赖时,Spring Boot会创建默认的内存 ...

  4. linux读取Windows的txt文件问题

    问题:Windows下生成的txt文件,在Linux下读取时会读取到多余字符(如: ^M) 原因:Windows和Linux下的换行符不一致 解决:在Linux代码中将多余字符去掉 ) buf = b ...

  5. Atcoder Beginner Contest 118 D-Match Matching(完全背包)

    题目链接 题意就是给N根火柴,M个数(M只能是1到9,对应的数字也只能是1到9),只能用这M个出现过的数(但每个数可以随便用多少个,只要火柴够)来拼出一个数字(拼出1,2,3,4,5,6,7,8,9分 ...

  6. JSON 解析 (二)—— Jackson的使用

    Jackson是基于Java语言的一种JSON和Java对象的数据处理工具.功能上简单易用,性能上根据目前主流转换工具比较,Jackson相对比较高效. <dependency> < ...

  7. Oracle查看表空间,创建表空间

    查看表空间: SELECT tablespace_name, file_id, file_name, round(bytes / (1024 * 1024), 0) total_space FROM ...

  8. Tomcat的四种web应用部署方式详解

    在Tomcat中有四种部署Web应用的方式,简要的概括分别是: (1)利用Tomcat自动部署 (2)利用控制台进行部署 (3)增加自定义的Web部署文件(%Tomcat_Home%\conf\Cat ...

  9. float数组转字符串实施方案小记

    float[] floats = {1.2f , 3.5f , 6.4f}; Double[] doubles = IntStream.range(0, floats.length).mapToDou ...

  10. hadoop安装要领

    1.安装JDK tar -zxvf jdk-7u75-linux-i586.tar.gz -C /root/training/ vi ~/.bash_profile JAVA_HOME=/root/t ...