这道题目的难度估计是noip之壁了吧。。。
70分的模拟做法之前已经讲过了,现在来说说100分的倍增做法。
首先,读入海拔后,我们可以预处理出从任意一个城市出发, 小A与小B能到达的下一个城市。思路就这么短,但代码非常繁琐,我感觉这部分甚至比倍增还麻烦。我们需要先将城市编号与海拔存在结构体内,对结构体按海拔高低进行排序,然后从1号城市到n号城市寻找其左右相邻的两个城市(还要这样离得最近),判断出来后通过链表记录前驱后继来删除该节点,将每一种情况都考虑到,还要注意是否越界。。。我个人一开始想的太简单,后来一点一点改,不断尝试输出数据直到正确为止,花了我两个半小时。。。这里讲讲能让这部分简单的方法吧。可以将数组的0位和n+1、n+2位设成非常大的数,然后对处在1位置上的数进行特判,这样一来我们的边界情况只用考虑左边界,而且可以解决。我的链表是按照位置存的,排完序后我还开了一个to数组记录某个城市排序后所在的位置。这样在枚举城市时可以直接用to[i]代表当前城市所在位置,而链表又是按照位置存的,相对来说比较方便。处理完这个问题,我们就需要用倍增解决剩下的问题了。我们定义go[i][j]代表从第i号城市出发,经过2^j轮所到达的城市,注意这里的轮是指小A小B都走过了,而且一定是小A先走的。定义A[i][j]代表小A从第i号城市出发,经过2^j轮所经过的路程,B[i][j]代表小A从第i号城市出发后小B走,经过2^j轮所经过的路程。这里的i一定是在一轮内的i,举个例子,go[i][0],i为1,1号城市到2号城市海拔差为6,2号到3号为5,那么A[i][0]=6,B[i][0]=5。明白这一点后,我们需要对倍增数组初始化,go[i][0]就是tb[ta[i]],也就是A走到某个城市后B在这个城市的基础上再走所到达的城市。A[i][0]就是小A从i出发到达城市的海拔减去一开始所在城市海拔的绝对值,B[i][0]就是在某一轮内从i号城市出发,最后到达的城市的海拔减去小A到达的城市的海拔的绝对值(为什么是这样,上面有例子了)。然后我们可以从1-20更新倍增数组,思路和一般的倍增差不多。得到了以上信息,我们就可以回答题目问的问题了。第一问是对于给定的最大路程,求从哪个城市出发小A/小B的值最小。那么我们写一个函数f(start,x),代表从sta