【题解】

  本题有多种做法,例如可持久化并查集、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」归程的更多相关文章

  1. loj#2718. 「NOI2018」归程

    题目链接 loj#2718. 「NOI2018」归程 题解 按照高度做克鲁斯卡尔重构树 那么对于询问倍增找到当前点能到达的高度最小可行点,该点的子树就是能到达的联通快,维护子树中到1节点的最短距离 s ...

  2. LOJ #2718. 「NOI2018」归程 Dijkstra+可持久化并查集

    把 $Noi2018$ day1t1 想出来还是挺开心的,虽然是一道水题~ 预处理出来 1 号点到其它点的最短路,然后预处理边权从大到小排序后加入前 $i$ 个边的并查集. 这个并查集用可持久化线段树 ...

  3. LOJ #2718. 「NOI2018」归程(Dijkstra + Kruskal重构树 + 倍增)

    题意 给你一个无向图,其中每条边有两个值 \(l, a\) 代表一条边的长度和海拔. 其中有 \(q\) 次询问(强制在线),每次询问给你两个参数 \(v, p\) ,表示在 \(v\) 出发,能开车 ...

  4. #2718. 「NOI2018」归程 kruskal重构树

    链接 https://loj.ac/problem/2718 思路 我们希望x所在的连通块尽量的大,而且尽量走高处 离线的话可以询问排序,kruskal过程中更新答案 在线就要用kruskal重构树 ...

  5. LOJ #2721. 「NOI2018」屠龙勇士(set + exgcd)

    题意 LOJ #2721. 「NOI2018」屠龙勇士 题解 首先假设每条龙都可以打死,每次拿到的剑攻击力为 \(ATK\) . 这个需要支持每次插入一个数,查找比一个 \(\le\) 数最大的数(或 ...

  6. loj#2721. 「NOI2018」屠龙勇士

    题目链接 loj#2721. 「NOI2018」屠龙勇士 题解 首先可以列出线性方程组 方程组转化为在模p意义下的同余方程 因为不保证pp 互素,考虑扩展中国剩余定理合并 方程组是带系数的,我们要做的 ...

  7. Loj #2719. 「NOI2018」冒泡排序

    Loj #2719. 「NOI2018」冒泡排序 题目描述 最近,小 S 对冒泡排序产生了浓厚的兴趣.为了问题简单,小 S 只研究对 *\(1\) 到 \(n\) 的排列*的冒泡排序. 下面是对冒泡排 ...

  8. 「NOI2018」归程

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

  9. 洛谷 8 月月赛 & 「PMOI」Round · 04

    T1 T166167 「PMOI-4」人赢 题目大意 给一个数列的前两项分别为\(n\)和\(m\) 当\(i\geq3\)时\(a_i = a_{i-1}*a_{i-2}\)的个位 给定\(n\), ...

随机推荐

  1. Real-Time Compressive Tracking,实时压缩感知跟踪算法解读

    这是Kaihua Zhang发表在ECCV2012的paper,文中提出了一种基于压缩感知(compressive sensing)的单目标跟踪算法,该算法利用满足压缩感知(compressive s ...

  2. sql让时间调前,调后的语句

    时间调前,调后 select billid,DATEADD(mm,2,billdate) from bi_Bill 注:用dateadd(/时间年/月/日,调前或后多少,字段) mm为月份,2为调前两 ...

  3. bzoj 1623: [Usaco2008 Open]Cow Cars 奶牛飞车【排序+贪心】

    从小到大排个序,然后能选就选 #include<iostream> #include<cstdio> #include<algorithm> using names ...

  4. bzoj 1682: [Usaco2005 Mar]Out of Hay 干草危机【并查集+二分】

    二分答案,把边权小于mid的边的两端点都并起来,看最后是否只剩一个联通块 #include<iostream> #include<cstdio> using namespace ...

  5. 清北考前刷题day2早安

    /* 做法一:按h sort一遍,对于一段区间[i,j],高度花费就是h[j]-h[i] 然后枚举区间,把区间内C排序,一个一个尽量选即可. n^3logn 标算:n^3 dp 高度排序,保证从前往后 ...

  6. spring data elasticsearch的 @Documnet 和 @Field 注解

    @Documnet 注解 public @interface Document { String indexName(); //索引库的名称,个人建议以项目的名称命名 String type() de ...

  7. 纵横填字js

    新数据结构设计: 定义一个map: key是横纵坐标字符串,比如“0,4” value是一个json,包含以下属性:字,横向的词(若 有的话,无的话,空串),纵向的词(若有的话,无的话,空串). 另有 ...

  8. RS485通信和Modbus协议(转)

    转自:http://www.51hei.com/bbs/dpj-23230-1.html 在工业控制.电力通讯.智能仪表等领域,通常情况下是采用串口通信的方式进行数据交换.最初采用的方式是RS232接 ...

  9. Android ViewPager+HorizontalScrollView实现标题栏滑动(腾讯新闻)

    1) ViewPager提供了左右滑动切换页面的方法,但是它所提供的标题只是无语,估计没有真正的项目会照搬拿过来;并且它只能一页一页滑,我想直接查看最后一页要滑半天; 2) 看了腾讯新闻客户端感觉体验 ...

  10. unbuntu系统:python2.7安装pyspark

    以前在进行搜索引擎rank-svm排序模型训练时,直接使用python读取的HDFS日志文件.统计计算等预处理操作再进行svm模型,最终产生出训练模型.现在回想一下,数据预处理这一块完全可以使用spa ...