第一次参加NOI,当然,我没去现场做,只是在网络同步赛做了而已。
那网站,特别特别卡啊……
最后只交了第一题,原本认为能AC,但是因为某些原因只有50分。
我这可怜的第一次啊……

题目

题目点此处下载,密码:ghn5

思考过程

看完了所有题,就来思考第一题。
曾经的GDKOI和GDOI给我留下了不可磨灭的印象:感觉上这些题似乎都只能靠水分。
所以,我从一开始就想着打水法。
想着想着,感觉可以打个80分。好开心!
开打。
打了4000多byte,完成得差不多了,突然发现,啊,我想到正解了!!!
把这个4000多byte的程序弃掉,思考了一阵子,然后开打。
打了好久,有3000多byte,尴尬的是,过了前四个样例,却,被第五个样例卡掉了。
我好慌,好慌……
然后发现,我程序跑得慢的原因,是最短路花的时间太多了。
一世英名,卡在了最短路上。
我看看那个TLE掉的Dijsktra,不信邪,打了个SPFA。
依然被卡,于是,我决定重打一遍Dijsktra!
这一次,秒过……
然后我就愉快地交了程序……

解法

题目的意思是在图中,先走一段没有积水的路径,这些代价是免费的,然后在走到终点。
先想想该怎么搞离线的做法。
首先,肯定要求一遍最短路。
把问题转化一下,现在有积水的边不能走,你只能走没有积水的边。
答案即是你可以走到的的点中,最短路值最小的。
立体化地想一想,如果一开始没有水,然后雨越下越大,水位逐渐升高。
原本图是一个联通块,然后随着一些边的淹没,被逐渐分成了许多小的联通块。
不妨反过来想想。
可以做一遍最大生成树,维护联通块中最短路的最小值,在做的过程中统计答案。
这就是离线做法。
怎么在线呢?
维护联通块中最大值中,我用的是并查集。
既然非要在线,那就用可持久化并查集!!!
那样就可以询问历史版本,就可以在线做了,哈哈哈哈哈哈哈哈哈……
如果点xx所表示的集合要并到yy所表示的集合中时,在xx上记录一下两者联通的最高海拔。
并试着更新一下yy上维护的,表示联通块中最短路的最小值。
然而,我们需要记录一下历史版本。怎么记录?
直接暴力记录啊!反正最大生成树中,一共会连N−1N−1条边,那么,顶多更新N−1N−1次。
在每个点上存它的历史状态,直接简单粗暴的在一个数组里记录一条信息,表示某个点,在某个水位时,最短路最小值是多少。
搞完最大生成树后,排个序,然后一段区间对应的就是一个点的修改信息。
那么在询问时,先在并查集上不断往上跳,直到跳不了(再跳就被水淹没了)。
然后在这个点的修改信息中,二分出来,得出答案。
时间复杂度:
O(NlgN(Dijsktra)+(MlgM+MlgN)(最大生成树)+NlgN(排序)+QlgN(询问))=O(MlgM+(N+M+Q)lgN)O(Nlg⁡N(Dijsktra)+(Mlg⁡M+Mlg⁡N)(最大生成树)+Nlg⁡N(排序)+Qlg⁡N(询问))=O(Mlg⁡M+(N+M+Q)lg⁡N)

代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 200000
#define MAXM 400000
int n,m;
struct edge
{int u,v,l,a;
} ed[MAXM+1];
bool cmped(const edge &x,const edge &y)
{return x.a>y.a;
}
struct EDGE
{int to,l,a;EDGE *las;
} e[MAXM*2];
int ne;
EDGE *last[MAXN+1];
void link(int u,int v,int l,int a)
{e[ne].to=v,e[ne].l=l,e[ne].a=a;e[ne].las=last[u];last[u]=e+ne;++ne;
}
long long dis[MAXN+1];
void Shortest_Path();
int Q,K,S;
struct Change_List
{int x,a;long long ans;
} cl[MAXN*2+1];
int ncl;
bool cmpcl(const Change_List &u,const Change_List &v)
{return u.x<v.x || u.x==v.x && (u.a>v.a || u.a==v.a && u.ans>v.ans);
}
int ac[MAXN+1];
struct Union_Find_Set
{int fa;int a;long long ans;int dep;
} ufs[MAXN+1];
int getfa(int x)
{while (ufs[x].fa!=x)x=ufs[x].fa;return x;
}
int main()
{
//  freopen("return.in","r",stdin);
//  freopen("return.out","w",stdout);freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);int T;scanf("%d",&T);while (T--){scanf("%d%d",&n,&m);memset(last,0,sizeof last);ne=0;for (int i=1;i<=m;++i){int u,v,l,a;scanf("%d%d%d%d",&u,&v,&l,&a);link(u,v,l,a);link(v,u,l,a);ed[i].u=u,ed[i].v=v,ed[i].l=l,ed[i].a=a;}scanf("%d%d%d",&Q,&K,&S);Shortest_Path();sort(ed+1,ed+m+1,cmped);for (int i=1;i<=n;++i){ufs[i].fa=i;ufs[i].a=S+1;ufs[i].ans=dis[i];ufs[i].dep=1;}ncl=0;for (int i=1;i<=n;++i){++ncl;cl[ncl].x=i;cl[ncl].ans=dis[i];cl[ncl].a=S+1;}for (int i=1;i<=m;++i){int x=getfa(ed[i].u),y=getfa(ed[i].v);if (x!=y){//x->yif (ufs[x].dep>ufs[y].dep)swap(x,y);ufs[x].fa=y;ufs[x].a=ed[i].a;ufs[y].dep=max(ufs[y].dep,ufs[x].dep+1);if (ufs[x].ans<ufs[y].ans){ufs[y].ans=ufs[x].ans;++ncl;cl[ncl].x=y;cl[ncl].ans=ufs[x].ans;cl[ncl].a=ed[i].a;}}}sort(cl+1,cl+ncl+1,cmpcl);for (int i=1,j=0;i<=ncl;++i)if (cl[i-1].x!=cl[i].x)ac[j++]=i-1;ac[n]=ncl;long long lastans=0;while (Q--){int v,p;scanf("%d%d",&v,&p);v=(v+K*lastans-1)%n+1;p=(p+K*lastans)%(S+1);while (v!=ufs[v].fa && p<ufs[v].a)v=ufs[v].fa;int l=ac[v-1]+1,r=ac[v],res=-1;while (l<=r){int mid=l+r>>1;if (p<cl[mid].a)l=(res=mid)+1;elser=mid-1;}lastans=cl[res].ans;printf("%lld\n",lastans);}}return 0;
}
bool cmph(int son,int fa)
{return dis[son]>dis[fa];
}
int h[MAXN],nh;
bool bz[MAXN+1];
void Shortest_Path()
{memset(dis+1,127,sizeof(long long)*n);memset(bz+1,0,sizeof(bool)*n);dis[1]=0;nh=1;h[0]=1;bz[1]=1;while (nh){int top=h[0];pop_heap(h,h+nh--,cmph);for (EDGE *ei=last[top];ei;ei=ei->las)if (dis[top]+ei->l<dis[ei->to]){dis[ei->to]=dis[top]+ei->l;if (!bz[ei->to]){bz[ei->to]=1;h[nh++]=ei->to;push_heap(h,h+nh,cmph);}}bz[top]=0;}
}

Others

1、 我比赛时没切题,是因为数组开小了……
2、 其实这个程序还有改进的地方,比如,在这题中,一些边的海拔是相同的,但我在最大生成树是会记录多条修改信息,其实可以并在一起。改起来也简单,但我懒得改了。

转载于:https://www.cnblogs.com/jz-597/p/11145285.html

NOI2018 Day1 归程(return)相关推荐

  1. NOI2018 Day1 归程(Kruskal重构树)

    目录 NOI2018 Day1 return 题解 AC代码: NOI2018 Day1 return 题解 作为NOI Day1 的T1,这道题目还是比较清真的(虽然自己在同步赛的时候只打了70分的 ...

  2. 【NOI2018】归程(kruskal重构树)

    这道题最后会化为这么一个问题:给一张图,每条边都有边权,多组询问,每次给出 u , k u,k u,k,问从 u u u 开始走,只走边权 ≤ k \leq k ≤k 的边,请维护 u u u 能走到 ...

  3. loj 2718. 「NOI2018」归程

    题意: 给一个图,每次询问从某个点出发,先坐车经过一些权值大于pp<script type="math/tex" id="MathJax-Element-31&qu ...

  4. 【知识点总结】【CSP考前复习】图论大杂烩【未完】

    序言 临近NOIP CSP-J 2019,不由得有些惆怅. 惆怅不是为了别的,主要是觉得从接触信息学竞赛开始,这已经是四个年头了,却一直拿的是二等奖.而今年是我最后的机会.如果不能成功,那自然就是AF ...

  5. LibreOJ 题解汇总

    目录 #1. A + B Problem #2. Hello, World! #3. Copycat #4. Quine #7. Input Test #100. 矩阵乘法 #101. 最大流 #10 ...

  6. 不要网上乱拷贝代码了!一段网上找的代码突然炸了!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 陈宏鸿 https://www.cnblogs.com/aspwe ...

  7. Joda-Time中两个日期之间的天数

    本文翻译自:Number of days between two dates in Joda-Time How do I find the difference in Days between two ...

  8. comet OJ 01背包

    01 背包 已经提交 尚未通过 时间限制:1000ms 内存限制:256MB 33.33% 提交人数:3 通过人数:1 题目描述 杨总有 mm 元,他来到了一个商场.这个商场共有 nn 种物品,每种物 ...

  9. java如何计算时间天数差,java计算两个时间相差天数的方法汇总

    问题描述: 输入:两个日期 输出:两个日期相差的天数 具体代码实现 方法1: 通过calendar类的日期比较.注意:这里需要考虑一下: 日期是跨年份的,如一个是2012年,一个是2015年的 年份是 ...

最新文章

  1. 病人还能生存多久?现在AI能给出更精准的预测
  2. Uva1103 古代象形符号
  3. MySQL单表多字段模糊查询解决方法
  4. lambda表达式_在Java 7或更早版本中使用Java 8 Lambda表达式
  5. SQL优化常用方法10
  6. IT团队之非正式沟通
  7. 【图像处理opencv】_Jupyter基本操作
  8. 冰雪奇缘,白色世界:四个IT人的四姑娘山双桥沟游记
  9. 获取一个 Byte 的各个 Bit 值
  10. jaxl php,php往mysql写数据,中文乱码有关问题
  11. vue不是内部或外部命令_vue脚手架
  12. Ubuntu ROS Kinect2安装
  13. ubuntu 安装 mysql debug_ubuntu 安装phpstorm+xdebug 动态调试环境
  14. 数据合并concat
  15. STC51单片机-实验开发装置仿真-物联网应用系统设计
  16. excel合并两列内容_【238期】EXCEL扩展思维,一题多解,玩转数据两列合并,你都会?...
  17. windows放到Linux替换,windows过渡到linux之软件的替换
  18. 二维码扫描枪中文开发指导
  19. mercury重置密码后服务器无响应,melogin.cn打不开的解决办法 水星路由器重置完无法上网...
  20. BP神经网络原理简单介绍以及公式推导(矩阵形式和分量形式)

热门文章

  1. 电脑安装python为什么显示的是程序丢失-python报错:无法启动此程序,因为计算机中丢失...
  2. python可以写桌面软件吗-Python学习,给自己的代码做个合集,定制自己的桌面软件!...
  3. vscode使用教程python-使用VS Code开发Python
  4. python详细基础教程-Python基础教程,Python入门教程(非常详细)
  5. python怎么导入文件-Python文件如何引入?详解引入Python文件步骤
  6. python语言介绍-Python语言的简介
  7. 学python需要什么文化基础-和尧名大叔一起从0开始学Python编程-循环
  8. python编程小游戏-使用Python写一个小游戏
  9. python自动搜索爬取下载文件-python批量爬取下载抖音视频
  10. 学python用什么书-python有什么好的书籍