今年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. 游标cursor案例

  2. 解决ssh ltt3.bg.cn 'jps' bash: jps: command not found 问题

    >>提君博客原创  http://www.cnblogs.com/tijun/  << linux 上我用hadoop用户配置好SSH后,运行 ssh ltt3.bg.cn ' ...

  3. MySQL系列:视图基本操作(3)

    1. 视图简介 1.1 视图定义 视图是一种虚拟的表,是从数据库中一个或多个表中导出来的表. 视图可以从已存在的视图的基础上定义. 数据库中只存放视图的定义,并没有存放视图中的数据,数据存放在原来的表 ...

  4. LodopJS文档式模版的加载和赋值

    Lodop模版有两种方法,一种是传统的JS语句,可以用JS方法里的eval来执行,一种是文档式模版,是特殊格式的base64码,此篇博文介绍文档式模版的加载,文档式模版的生成以及传统JS模版的生成加载 ...

  5. Jenkins+PowerShell持续集成环境搭建(六)参数化构建

    参数化构建可以应用于动态绑定源码地址等情况. 勾选“This build is parameterized”: 如果需要动态绑定源码地址,参考: 配置完成后构建项目变成:

  6. const函数

    1. const修饰成员函数:表示不可以修改成员变量 class test{ public: test(){ i_ = ; } int Get() const{ //i_ = 0; //error:不 ...

  7. Nginx 优先选择连接最少的上游服务器

    详见陶辉87课 upstream test { server ; server ; least_conn ; zone backends 64k; }

  8. 【Python】一份非常好的Matplotlib教程

    Matplotlib 教程 本文为译文,原文载于此,译文原载于此.本文欢迎转载,但请保留本段文字,尊重作者和译者的权益.谢谢.: ) 介绍 Matplotlib 可能是 Python 2D-绘图领域使 ...

  9. Spring MVC 使用介绍(二)—— DispatcherServlet

    一.Hello World示例 1.引入依赖 <dependency> <groupId>javax.servlet</groupId> <artifactI ...

  10. JQ用法

    jQuery简称jq,是一款同prototype一样优秀js开发库类,特别是对css和XPath的支持,使我们写js变得更加方便!如果你不是个js高手又想写出优 秀的js效果,jq可以帮你达到目的!下 ...