洛谷 4768 LOJ 2718「NOI2018」归程

【题解】
本题有多种做法,例如可持久化并查集、kruskal重构树等。
kruskal重构树的做法是这样的:先把边按照海拔h从大到小的顺序排序,然后跑kruskal建立海拔的最大生成树,顺便建kruskal重构树。
这样建出来的重构树是一个小根堆,也就是说,如果某个节点没有被淹,它的子树内的点都不会被淹,它们可以互相开车到达。
我们建重构树的时候维护每个节点的子树内的点到1号点的最小距离mn,mn先用dijkstra处理好。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define rg register
#define N 400010
using namespace std;
int T,n,m,q,k,s,tot,cnt,last[N],f[N],pos[N],p[N][],hei[N];
LL ans,mn[N];
struct edge{
int to,pre,dis;
}e[N<<];
struct rec{
int u,v,h;
}r[N<<];
struct heap{
LL d;int p;
}h[N];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
inline void up(int x){
int fa;
while((fa=(x>>))&&h[fa].d>h[x].d) swap(h[x],h[fa]),swap(pos[h[x].p],pos[h[fa].p]),x=fa;
}
inline void down(int x){
int son;
while((son=(x<<))<=tot){
if(son<tot&&h[son].d>h[son+].d) son++;
if(h[son].d<h[x].d) swap(h[x],h[son]),swap(pos[h[x].p],pos[h[son].p]),x=son;
else return;
}
}
inline void dijkstra(int x){
for(rg int i=;i<=(n<<);i++) mn[i]=4e9;
h[tot=pos[x]=]=(heap){mn[x]=,x};
while(tot){
int now=h[].p; pos[h[tot].p]=; h[]=h[tot--]; if(tot) down();
for(rg int i=last[now],to;i;i=e[i].pre)
if(mn[to=e[i].to]>mn[now]+e[i].dis){
mn[to]=mn[now]+e[i].dis;
if(!pos[to]) h[pos[to]=++tot]=(heap){mn[to],to};
else h[pos[to]].d=mn[to];
up(pos[to]);
}
}
}
inline int climb(int x,int y){
for(rg int i=;i>=;i--) if(hei[p[x][i]]>y) x=p[x][i]; return x;
}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
inline bool cmp(rec a,rec b){return a.h>b.h;}
inline void Pre(){
tot=; cnt=; ans=;
memset(last,,sizeof(last));
memset(pos,,sizeof(pos));
memset(p,,sizeof(p));
}
int main(){
freopen("return.in","r",stdin);
freopen("return.out","w",stdout);
T=read();
while(T--){
Pre();
n=read(); m=read();
for(rg int i=;i<=m;i++){
int u,v,d;
r[i].u=u=read(),r[i].v=v=read(),d=read(),r[i].h=read();
e[++tot]=(edge){v,last[u],d}; last[u]=tot;
e[++tot]=(edge){u,last[v],d}; last[v]=tot;
}
dijkstra();
// for(rg int i=1;i<=n;i++) printf("%d ",mn[i]); puts("mn");
tot=n;
sort(r+,r++m,cmp);
for(rg int i=;i<=n;i++) f[i]=i,f[i+n]=i+n;
for(rg int i=;i<=m;i++){
int u=find(r[i].u),v=find(r[i].v);
if(u!=v){
hei[++tot]=r[i].h; mn[tot]=min(mn[u],mn[v]);
f[u]=f[v]=p[u][]=p[v][]=tot;
cnt++;
}
if(cnt==n-) break;
}
for(rg int j=;j<;j++)
for(rg int i=;i<=tot;i++) p[i][j]=p[p[i][j-]][j-]; q=read(); k=read(); s=read();
while(q--){
int v0=(read()+k*ans-)%n+,p0=(read()+k*ans)%(s+);
// printf("v0=%d p0=%d\n",v0,p0);
printf("%lld\n",ans=mn[climb(v0,p0)]);
}
}
return ;
}
那么对于每个出发点为v的询问,我们倍增找到它最早的不被淹的祖先p,答案就是mn[p].
洛谷 4768 LOJ 2718「NOI2018」归程的更多相关文章
- loj#2718. 「NOI2018」归程
题目链接 loj#2718. 「NOI2018」归程 题解 按照高度做克鲁斯卡尔重构树 那么对于询问倍增找到当前点能到达的高度最小可行点,该点的子树就是能到达的联通快,维护子树中到1节点的最短距离 s ...
- LOJ #2718. 「NOI2018」归程 Dijkstra+可持久化并查集
把 $Noi2018$ day1t1 想出来还是挺开心的,虽然是一道水题~ 预处理出来 1 号点到其它点的最短路,然后预处理边权从大到小排序后加入前 $i$ 个边的并查集. 这个并查集用可持久化线段树 ...
- LOJ #2718. 「NOI2018」归程(Dijkstra + Kruskal重构树 + 倍增)
题意 给你一个无向图,其中每条边有两个值 \(l, a\) 代表一条边的长度和海拔. 其中有 \(q\) 次询问(强制在线),每次询问给你两个参数 \(v, p\) ,表示在 \(v\) 出发,能开车 ...
- #2718. 「NOI2018」归程 kruskal重构树
链接 https://loj.ac/problem/2718 思路 我们希望x所在的连通块尽量的大,而且尽量走高处 离线的话可以询问排序,kruskal过程中更新答案 在线就要用kruskal重构树 ...
- LOJ #2721. 「NOI2018」屠龙勇士(set + exgcd)
题意 LOJ #2721. 「NOI2018」屠龙勇士 题解 首先假设每条龙都可以打死,每次拿到的剑攻击力为 \(ATK\) . 这个需要支持每次插入一个数,查找比一个 \(\le\) 数最大的数(或 ...
- loj#2721. 「NOI2018」屠龙勇士
题目链接 loj#2721. 「NOI2018」屠龙勇士 题解 首先可以列出线性方程组 方程组转化为在模p意义下的同余方程 因为不保证pp 互素,考虑扩展中国剩余定理合并 方程组是带系数的,我们要做的 ...
- Loj #2719. 「NOI2018」冒泡排序
Loj #2719. 「NOI2018」冒泡排序 题目描述 最近,小 S 对冒泡排序产生了浓厚的兴趣.为了问题简单,小 S 只研究对 *\(1\) 到 \(n\) 的排列*的冒泡排序. 下面是对冒泡排 ...
- 「NOI2018」归程
「NOI2018」归程 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 >\(1\) 个节点. \(m\) 条边的无向连通图(节点的编号从 \( ...
- 洛谷 8 月月赛 & 「PMOI」Round · 04
T1 T166167 「PMOI-4」人赢 题目大意 给一个数列的前两项分别为\(n\)和\(m\) 当\(i\geq3\)时\(a_i = a_{i-1}*a_{i-2}\)的个位 给定\(n\), ...
随机推荐
- python-----使用requirements.txt批量安装包
首先写一个 requirements.txt,格式如图: 然后使用命令行,到 requirements.txt 所在的目录下,执行命令: pip install -r requirements.txt ...
- JAVA线程同步 (二)notify()与notifyAll()-***
编写多线程程序需要进行线程协作,前面介绍的利用互斥来防止线程竞速是来解决线程协作的衍生危害的.编写线程协作程序的关键是解决线程之间的协调问题,在这些任务中,某些可以并行执行,但是某些步骤需要所有的任务 ...
- JS动态加载JS
1.直接document.write <script language="javascript"> document.write("<scrip ...
- JSP页面结构
1.表达式格式(experssion):<%=value %>//用来在页面中调用java表达式,从而得到返回值 <%=new java.util.Date();%> 2.小脚 ...
- 为了一个句号,写了好多行的代码——值!(html 表单的处理)
个人信息表 <span style="font-size:18px;"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML ...
- extjs grid禁止表格头部使用鼠标拖拽改变宽度
extjs6 经典版 表格头部使用鼠标拖动 禁止改变列的宽度 只需要给grid 设置属性enableColumnResize:false就可以啦 xtype:'grid', enableColumnR ...
- java8的LocalDateTime与Date互相转换
LocalDateTime转Date Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date ...
- JavaScript相关技术学习
百度前端技术学院 http://ife.baidu.com/task/all 框架 JQuery 简单Web论坛 https://github.com/huanshen/web-bbs http:/ ...
- SQL远程连接
一.添加远程连接EXEC sp_addlinkedserver @server = '254', @srvproduct = '',--链接服务器的 OLE DB 数据源的产品名称 @provi ...
- CF 334 div.2-D Moodular Arithmetic
思路: 易知k = 0的时候答案是pp-1,k = 1的时候答案是pp. 当k >= 2的时候,f(0) = 0,对于 1 <= n <= p - 1,如果f(n)确定,由题意可知f ...