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代码整合
随机推荐
- Leecode刷题之旅-C语言/python-66加一
/* * @lc app=leetcode.cn id=66 lang=c * * [66] 加一 * * https://leetcode-cn.com/problems/plus-one/desc ...
- FPGA算法学习(1) -- Cordic(圆周系统之向量模式)
旋转模式用来解决三角函数,实现极坐标到直角坐标的转换,基础理论请参考Cordic算法--圆周系统之旋转模式.那么,向量模式则用来解决反三角函数的问题,体现的应用主要是直角坐标向极坐标转换,即已知一点的 ...
- app:showAsAction 和android:showAsAction
app:showAsAction 它有三个可选项1.always:总是显示在界面上2.never:不显示在界面上,只让出现在右边的三个点中3.ifRoom:如果有位置才显示,不然就出现在右边的三个点中 ...
- WPF中的命令与命令绑定(二)
原文:WPF中的命令与命令绑定(二) WPF中的命令与命令绑定(二) 周银辉在WPF中,命令(Commandi ...
- 数据迁移的应用场景与解决方案Hamal
本文来自网易云社区 作者:马进 跑男热播,作为兄弟团忠实粉丝,笔者也是一到周五就如打鸡血乐不思蜀. 看着银幕中一众演员搞怪搞笑的浮夸演技,也时常感慨,这样一部看似简单真情流露的真人秀,必然饱含了许许多 ...
- MD5、SHA校验命令
linux系统的软件很多时候都以境像的方式提供下载,但我们如何确实下载的文件是没有被篡改过的呢?Linux中一般用对下载的文件进行MD5和SHA校验来确认. MD5 我们拿iptraf软件来试验: 我 ...
- Scala学习笔记(四):从文件里读取文本行
第一个版本: import scala.io.Source if(args.length>0){ for(line<-Source.fromFile(args(0)).getLines) ...
- 虚拟现实-VR-UE4-创建C++版工程
首先,创建C++版本的UE4 项目工程,我使用的是4.12.3版本,据了解,新版本后面的编译都是vs2015 所以,想要创建C++版本的工程,就需要安装vs2015 至于vs2015的安装,自己百度吧 ...
- Selenium八大元素定位方式
1.根据id来定位: import org.openqa.selenium.By;import org.openqa.selenium.WebDriver;import org.openqa.sele ...
- 【LoadRunner】解决LR11无法录制Chrome浏览器脚本问题
LoadRunner录制脚本时,遇到高版本的IE.FireFox,或者Chrome浏览器,会出现无法录制脚本的问题,下面就来讲一下如何利用LR自带的wplus_init_wsock.exe插件进行脚本 ...