NOI2018 D1T1 [NOI2018]归程 解题报告
P4768 [NOI2018]归程
题目描述
本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定。
魔力之都可以抽象成一个 \(n\) 个节点、\(m\) 条边的无向连通图(节点的编号从 \(1\) 至 \(n\))。我们依次用 \(l,a\) 描述一条边的长度、海拔。
作为季风气候的代表城市,魔力之都时常有雨水相伴,因此道路积水总是不可避免的。由于整个城市的排水系统连通,因此有积水的边一定是海拔相对最低的一些边。我们用水位线来描述降雨的程度,它的意义是:所有海拔不超过水位线的边都是有积水的。
Yazid是一名来自魔力之都的OIer,刚参加完ION2018的他将踏上归程,回到他温暖的家。
Yazid 的家恰好在魔力之都的 \(1\) 号节点。对于接下来 \(Q\) 天,每一天Yazid 都会告诉你他的出发点 \(v\) ,以及当天的水位线\(p\)。 每一天,Yazid 在出发点都拥有一辆车。这辆车由于一些故障不能经过有积水的边。 Yazid 可以在任意节点下车,这样接下来他就可以步行经过有积水的边。但车会被留在他下车的节点并不会再被使用。
需要特殊说明的是,第二天车会被重置,这意味着:
- 车会在新的出发点被准备好。
- Yazid 不能利用之前在某处停放的车。Yazid 非常讨厌在雨天步行,因此他希望在完成回家这一目标的同时,最小化他步行经过的边的总长度。
请你帮助 Yazid 进行计算。
本题的部分测试点将强制在线,具体细节请见【输入格式】和【子任务】。
输入输出格式
输入格式:
单个测试点中包含多组数据。输入的第一行为一个非负整数\(T\),表示数据的组数。
接下来依次描述每组数据,对于每组数据:
第一行 \(2\) 个非负整数 \(n,m\),分别表示节点数、边数。
接下来 \(m\) 行,每行 \(4\) 个正整数\(u, v, l, a\),描述一条连接节点 \(u, v\) 的、长度为 \(l\)、海拔为 \(a\) 的边。 在这里,我们保证\(1 \leq u,v \leq n\)。
接下来一行 \(3\) 个非负数 \(Q, K, S\) ,其中 \(Q\) 表示总天数,\(K \in {0,1}\) 是一个会在下面被用到的系数,\(S\) 表示的是可能的最高水位线。
接下来 \(Q\) 行依次描述每天的状况。每行 \(2\) 个整数 \(v_0,p_0\)描述一天:
这一天的出发节点为
\(v = (v_0 + K \times \mathrm{lastans} - 1) \bmod n + 1\)。
这一天的水位线为
\(p = (p_0 + K \times \mathrm{lastans}) \bmod (S + 1)\)。
其中 lastans
表示上一天的答案(最小步行总路程)。特别地,我们规定第 \(1\) 天时 lastans = 0。 在这里,我们保证\(1 \leq v_0 \leq n,0 \leq p_0 \leq S\)。
对于输入中的每一行,如果该行包含多个数,则用单个空格将它们隔开。
输出格式:
依次输出各组数据的答案。对于每组数据:
输出 \(Q\) 行每行一个整数,依次表示每天的最小步行总路程。
所有测试点均保证 \(T\leq 3\),所有测试点中的所有数据均满足如下限制:
\(n\leq 2\times 10^5\),\(m\leq 4\times 10^5\),\(Q\leq 4\times 10^5\),\(K\in\left\{0,1\right\}\),\(1\leq S\leq 10^9\)。
对于所有边:\(l\leq 10^4\),\(a\leq 10^9\)。
如果在NOI考场上,这题一定不能挂。
如果你没学过虫狗鼠或者并茶几,那么只要你不写SPFA,在一个多个小时内稳稳拿到离线的65pts是没问题的。
可持久化并茶几我不会,不过虫狗鼠的思路挺简单的,会就是一眼题。
思路:
先按最大生成树建重构树,按照惯例顺手搞一下倍增,然后预处理1为源点的最短路,每次询问直接倍增找到大于水位的节点更新答案即可。
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
const int N=4e5+10;
struct Edge
{
int u,v,w;
bool friend operator <(Edge n1,Edge n2){return n1.w>n2.w;}
}e[N];
int head[N],to[N<<1],Next[N<<1],edge[N<<1],cnt;
void add(int u,int v,int w)
{
to[++cnt]=v,edge[cnt]=w,Next[cnt]=head[u],head[u]=cnt;
}
int F[N],f[N][20],n,m;
int Find(int x){return F[x]=F[x]==x?x:Find(F[x]);}
int dis[N<<1],used[N],poi[N<<1];
int min(int x,int y){return x<y?x:y;}
#define P std::pair <int,int>
std::priority_queue <P,std::vector <P>,std::greater <P> > q;
void disj()
{
memset(dis,0x3f,sizeof(dis));
memset(used,0,sizeof(used));
dis[1]=0;
q.push(std::make_pair(0,1));
while(!q.empty())
{
int u=q.top().second;
q.pop();
if(used[u]) continue;
used[u]=1;
for(int i=head[u];i;i=Next[i])
{
int v=to[i];
if(dis[v]>dis[u]+edge[i])
{
dis[v]=dis[u]+edge[i];
q.push(std::make_pair(dis[v],v));
}
}
}
}
int find(int v,int p)
{
for(int i=19;~i;i--)
if(poi[f[v][i]]>p)
v=f[v][i];
return dis[v];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(head,0,sizeof(head));
memset(f,0,sizeof(f));
memset(poi,0,sizeof(poi));
cnt=0;
scanf("%d%d",&n,&m);
int n_=n;
for(int w,i=1;i<=m;i++)
{
scanf("%d%d%d%d",&e[i].u,&e[i].v,&w,&e[i].w);
add(e[i].u,e[i].v,w),add(e[i].v,e[i].u,w);
}
for(int i=1;i<=n<<1;i++) F[i]=i;
disj();
std::sort(e+1,e+1+m);
for(int i=1;i<=m;i++)
{
int u=e[i].u,v=e[i].v;
int r1=Find(u),r2=Find(v);
if(r1==r2) continue;
F[r1]=F[r2]=f[r1][0]=f[r2][0]=++n;
poi[n]=e[i].w,dis[n]=min(dis[r1],dis[r2]);
}
for(int j=1;j<=19;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
int lastans=0,q,k,s;
scanf("%d%d%d",&q,&k,&s);
for(int v,p,i=1;i<=q;i++)
{
scanf("%d%d",&v,&p);
v=(v+k*lastans-1)%n_+1;
p=(p+k*lastans)%(s+1);
printf("%d\n",lastans=find(v,p));
}
}
return 0;
}
2018.10.17
NOI2018 D1T1 [NOI2018]归程 解题报告的更多相关文章
- 「NOI2018」屠龙勇士 解题报告
「NOI2018」屠龙勇士 首先对于每个龙用哪个剑砍,我们可以用set随便模拟一下得到. 然后求出拿这个剑砍这条龙的答案 \[ atk_ix-p_iy=a_i \] 其中\(atk_i\)是砍第\(i ...
- CH Round #56 - 国庆节欢乐赛解题报告
最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...
- 二模13day1解题报告
二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...
- BZOJ 1051 最受欢迎的牛 解题报告
题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4438 Solved: 2353[S ...
- 习题:codevs 2822 爱在心中 解题报告
这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...
- 习题:codevs 1035 火车停留解题报告
本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...
- 习题: codevs 2492 上帝造题的七分钟2 解题报告
这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...
- 习题:codevs 1519 过路费 解题报告
今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...
- NOIP2016提高组解题报告
NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合
随机推荐
- 2.5 进程控制之wait函数
一.绪论 一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果 是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是 ...
- Python基本图形绘制
turtle的一个画布空间最小单位是像素 turtle的绘制窗体:turtle.stup(width,heigth,startx,starty) 四个参数中后两个可选 turtle空间坐标体系:tur ...
- python3 练习题100例 (二十一)打印一定范围内的水仙花数
题目内容: 水仙花数是指一个n位数 (n≥3),它的每个位上的数字的n次幂之和等于它本身. 例如:153是一个“水仙花数”,因为 153 是个 3位数,而1**3+5**3+3**3==153. 输入 ...
- Java学习笔记十二:Java中方法的重载
Java中方法的重载 什么是方法的重载呢? 如果同一个类中包含了两个或两个以上方法名相同.方法参数的个数.顺序或类型不同的方法,则称为方法的重载,也可称该方法被重载了.如下所示 4 个方法名称都为 s ...
- python网络编程的坑(持续更新)
初学python,踩了许多坑...每天都学一点吧..(大佬绕过) 1.session的用法: session是python requests库中的一个重要功能.session可以存储用户的数据并且存储 ...
- JAVA 泛型之类型擦除
★ 泛型是 JDK 1.5 版本引进的概念,之前是没有泛型的概念的,但泛型代码能够很好地和之前版本的代码很好地兼容. CollectionTest.java ---编译成CollectionTest. ...
- (数据科学学习手札22)主成分分析法在Python与R中的基本功能实现
上一篇中我们详细介绍推导了主成分分析法的原理,并基于Python通过自编函数实现了挑选主成分的过程,而在Python与R中都有比较成熟的主成分分析函数,本篇我们就对这些方法进行介绍: R 在R的基础函 ...
- PHP批量替换MySql数据库中的数据内容
<?php //替换数据库内容类 class replace{ public $dbAddress; //数据库地址 public $dbUser; //数据库用户名 public $dbPwd ...
- jdk带的一些工具,强悍
这些工具有的已经接触到了,功能很强悍,但是使用也有点复杂(参数) 在代码中使用System.setProperty()或者在启动程序时使用-D选项设置代理服务器地址和端口 看看别人的研究: JDK自带 ...
- vuex模块相互调用
https://segmentfault.com/a/1190000009434398