洛谷P4768 [NOI2018]归程(可持久化并查集,最短路)

时间:2022-01-03 01:30:50

闲话

一个蒟蒻,在网络同步赛上进行了这样的表演——

T2组合计数不会,T3字符串数据结构不会,于是爆肝T1

一开始以为整个地图都有车,然后写了2h+的树套树,终于发现样例过不去

然后写可持久化并查集Debug到13:20过了前4个样例,然后第5个T飞了。

FST?

。。。。。。

FST!

完美收获50分暴力分。

原来是按秩合并那里咕咕了。

从50到100的蜕变,只需一行,你值的拥有。

思路

不会kruscal重构树

容易发现,假设我们确定了水位线,那么就确定了图中有哪些边是连通的。这时候的答案该如何确定呢?因为车可以在一个连通块里随便开,所以同一个连通块里的点的答案都是一样的,为连通块内离\(1\)最近的点到\(1\)的距离。

那当然要首先把单源最短路求出来。SPFA死了?被固定了?(参考生物必修3),还好蒟蒻写的是dijkstra。

因为并查集只能合并,所以我们要按高度从大到小排序依次加边。如果是离线那好办了,把询问也按高度排个序,每在并查集里加一条边就可以完成若干个询问。

那强制在线?当然要把合并过程中的每个版本都存起来啦!用可持久化并查集(蒟蒻之前写过一篇blog

当然,高度要离散化,为了让每个询问通过二分找到对应版本。

复杂度\(O(n\log m+(m+q)\log^2n)\),当然这里写的有点丑,在倒序合并的过程中可以在外面放并查集,祖先到并查集里跳,比在可持久化并查集里跳快多了,复杂度\(O(n\log m+m\log n+q\log^2n)\)。

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define UI unsigned int
#define RG register
#define I inline
#define R RG UI
#define G c=getchar()
using namespace std;
const int N=2e5+9,M=8e5+9,S=2e7;
struct NODE{
UI u,d;
I bool operator<(RG NODE x)const{return d>x.d;}
};//堆优化dijkstra的节点
struct EDGE{
UI u,v,a;
I bool operator<(RG EDGE x)const{return a<x.a;}
}e[M];//对边排序
priority_queue<NODE>q;
UI n,L,p,he[N],ne[M],to[M],l[M],a[M],b[M],d[N],rt[M],lc[S],rc[S],f[S],mn[S],dep[S];
bool vis[N];
I UI in(){
RG char G;
while(c<'-')G;
R x=c&15;G;
while(c>'-')x*=10,x+=c&15,G;
return x;
}
void build(R&u,R l,R r){//建初始并查集
u=++p;
if(l==r){mn[u]=d[f[u]=l];return;}
R m=(l+r)>>1;
build(lc[u],l,m);
build(rc[u],m+1,r);
}
UI ins(R*u,R v,R t){//插入
R l=1,r=n,m;
while(l!=r){
*u=++p;m=(l+r)>>1;
if(t<=m)r=m,rc[*u]=rc[v],u=lc+*u,v=lc[v];
else l=m+1,lc[*u]=lc[v],u=rc+*u,v=rc[v];
}
return *u=++p;
}
UI getf(R rt,R t){//跳祖先
R u,l,r,m;
while(1){
u=rt;l=1;r=n;
while(l!=r){
m=(l+r)>>1;
if(t<=m)r=m,u=lc[u];
else l=m+1,u=rc[u];
}
if(t==f[u])break;
t=f[u];
}
return u;
}
int main(){
freopen("return.in","r",stdin);
freopen("return.out","w",stdout);
R T=in(),m,i,j,u,v,w;
while(T--){
p=0;n=in();m=in();//时刻注意清空变量!
for(i=1;i<=m;++i){
u=in();v=in();
ne[++p]=he[u];to[he[u]=p]=v;
ne[++p]=he[v];to[he[v]=p]=u;
l[p]=l[p-1]=in();
e[i]=(EDGE){u,v,a[p]=a[p-1]=in()};
}
memset(d,-1,(n+1)<<2);//dijkstra开始
p=d[1]=0;q.push((NODE){1,0});
while(!q.empty()){
RG NODE cur=q.top();q.pop();
if(vis[u=cur.u])continue;
vis[u]=1;
for(i=he[u];i;i=ne[i])
if(d[to[i]]>d[u]+l[i])
q.push((NODE){to[i],d[to[i]]=d[u]+l[i]});
}
R q=in(),k=in(),s=in(),lans=0;
sort(e+1,e+m+1);
for(i=1;i<=m;++i)b[i]=e[i].a;
b[m+1]=s+1;L=unique(b+1,b+m+2)-b-1;//离散化,注意加入s+1
build(rt[L],1,n);
for(i=L-1,j=m;i;--i){
rt[i]=rt[i+1];
for(;j&&e[j].a==b[i];--j){
if((u=getf(rt[i],e[j].u))==(v=getf(rt[i],e[j].v)))continue;//可优化的地方
if(dep[u]>dep[v])swap(u,v);//按秩合并
f[ins(&rt[i],rt[i],f[u])]=f[v];
w=ins(&rt[i],rt[i],f[v]);
f[w]=f[v];mn[w]=min(mn[u],mn[v]);//因为按秩合并所以min必须要记
dep[w]=dep[v]+(dep[u]==dep[v]);//50分就是因为这一行!
}
}
while(q--){
v=(in()+k*lans-1)%n+1;u=(in()+k*lans)%(s+1);
printf("%u\n",lans=mn[getf(rt[upper_bound(b+1,b+L+1,u)-b],v)]);
}//谨慎选择lower_bound和upper_bound
memset(vis,0,n+1);
memset(he,0,(n+1)<<2);
memset(rt,0,(L+1)<<2);
memset(lc,0,(p+1)<<2);
memset(rc,0,(p+1)<<2);
memset(f,0,(p+1)<<2);
memset(mn,0,(p+1)<<2);
memset(dep,0,(p+1)<<2);//该清空的都要清空
}
return 0;
}

洛谷P4768 [NOI2018]归程(可持久化并查集,最短路)的更多相关文章

  1. 洛谷P4768 &lbrack;NOI2018&rsqb;归程 &lbrack;可持久化并查集,Dijkstra&rsqb;

    题目传送门 归程 格式难调,题面就不放了. 分析: 之前同步赛的时候反正就一脸懵逼,然后场场暴力大战,现在呢,还是不会$Kruskal$重构树,于是就拿可持久化并查集做. 但是之前做可持久化并查集的时 ...

  2. BZOJ5415&colon;&lbrack;NOI2018&rsqb;归程&lpar;可持久化并查集&comma;最短路&rpar;

    Description Input Output Sample Input1 14 31 2 50 12 3 100 23 4 50 15 0 23 02 14 13 13 2 Sample Outp ...

  3. 洛谷P4768 &lbrack;NOI2018&rsqb;归程(克鲁斯卡尔重构树&plus;最短路)

    传送门 前置技能,克鲁斯卡尔重构树 我们按道路的高度建一个最大生成树,然后建好克鲁斯卡尔重构树 那么我们需要知道一颗子树内到1点距离最近是多少(除此之外到子树内任何一个点都不需要代价) 可以一开始直接 ...

  4. 洛谷 P4768 &lbrack;NOI2018&rsqb;归程

    洛谷 361行代码的由来 数据分治大发好啊- NOI的签到题,可怜我在家打了一下午才搞了80分. 正解应该是kruskal重构树或排序+可持久化并查集. 我就分点来讲暴力80分做法吧(毕竟正解我也没太 ...

  5. &lbrack;NOI2018&rsqb; 归程 可持久化并查集

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

  6. &lbrack;NOI2018&rsqb;归程&lpar;可持久化并查集&comma;Kruskal重构树&rpar;

    解法一: 1.首先想到离线做法:将边和询问从大到小排序,并查集维护连通块以及每个连通块中所有点到1号点的最短距离.$O(n\log n)$ 配合暴力等可以拿到75分. 2.很容易想到在线做法,使用可持 ...

  7. &lbrack;洛谷P4768&rsqb; &lbrack;NOI2018&rsqb;归程 &lpar;kruskal重构树模板讲解&rpar;

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

  8. 洛谷P4768 &lbrack;NOI2018&rsqb;归程&lpar;Kruskal重构树&rpar;

    题意 直接看题目吧,不好描述 Sol 考虑暴力做法 首先预处理出从$1$到每个节点的最短路, 对于每次询问,暴力的从这个点BFS,从能走到的点里面取$min$ 考虑如何优化,这里要用到Kruskal重 ...

  9. 洛谷&dollar;P4768&bsol; &lbrack;NOI2018&rsqb;&dollar;归程 &dollar;kruscal&dollar;重构树

    正解:$kruscal$重构树 解题报告: 传送门$QwQ$ 语文不好选手没有*$TT$连题目都看不懂真的要哭了$kk$ 所以先放个题目大意?就说给定一个$n$个点,$m$条边的图,每条边有长度和海 ...

随机推荐

  1. 【转】getHibernateTemplate出现的所有find方法的总结

    一.find(String queryString); 示例:this.getHibernateTemplate().find("from bean.User"); 返回所有Use ...

  2. iOS开发多线程篇—线程间的通信(转)

    这里转载 给自己一个备份 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转 ...

  3. 05-3&period; 求a的连续和&lpar;15&rpar;

    输入两个整数a和n,a的范围是[0,9],n的范围是[1,8],求数列之和S = a+aa+aaa+...+aaa...a(n个a). 如a为2.n为8时输出的是2+22+222+...+222222 ...

  4. 吝啬的国度&lpar;dfs&plus;vector&rpar;

    吝啬的国度 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来.现在,Tom在第S号城市, ...

  5. 【转】CString与string、char&ast;的区别和转换

    我们在C++的开发中经常会碰到string.char*以及CString,这三种都表示字符串类型,有很多相似又不同的地方,常常让人混淆.下面详细介绍这三者的区别.联系和转换: 各自的区别 char*: ...

  6. Elasticsearch学习之配置小记

    基于 elasticsearch 1.4.4 版本.安装方式为RPM安装.所有涉及路径需根据实际情况来设置判断. 0x01 内存调整 调整ES内存分配有多种方式,建议调整 /etc/sysconfig ...

  7. Tools - Others

    01 - 一些网络工具 文档查阅 https://devdocs.io/ API文档 http://overapi.com/ 开源代码及文档搜索 https://searchcode.com/ 电子书 ...

  8. PAT B1013 数素数 (20 分)

    令 P​i​​ 表示第 i 个素数.现任给两个正整数 M≤N≤10​4​​,请输出 P​M​​ 到 P​N​​ 的所有素数. 输入格式: 输入在一行中给出 M 和 N,其间以空格分隔. 输出格式: 输 ...

  9. 安装及调试 Mavem Web

    一  使用Mavem eclipse菜单栏,找到file-->new -->other 然后找到Maven Project 然后next. 接着,选择maven-archetype-web ...

  10. Apache HttpComponents 获取inputStream

    package org.apache.http.examples.client; import java.io.IOException; import java.io.InputStream; imp ...