2064. 爬山
★☆ 输入文件:
mountain.in
输出文件:mountain.out
简单对比
时间限制:1 s 内存限制:256 MB【题目描述】
球有一天走在街上。
一个健身房发传单的人对球说:“来健身吗?还能减肥,挺好的!”。
球很不高兴。球一点都不觉得自己很胖,不过球还是决定去锻炼。
球最终选择了爬山。
球第一分钟位于海拔为a的地方。那之后,球每分钟可以向上爬不超过d米,也可以向下滚不超过d米,也可以原地不动(d米指的是竖直高度)。球在第n分
钟时位于海拔为b的地方。
球想知道,在不考虑山地形的情况下,他最高可以到过海拔为多少的地方。
【输入格式】
一行四个整数,分别为n,d,a,b,含义见题面描述。
【输出格式】
一行一个整数,表示答案。
【样例输入】
3 5 2 4【样例输出】
7【提示】
样例解释
球第一一分钟在海拔为2的位置,第二分钟向上爬5米到达海拔为7的位置,第三分钟向下滚3米到达海拔为4的位置。这样他到达过最高的地方海拔为7米。其他方案到过最高的地方都小于7米。
对于20%的数据,n=2。
对于60%的数据,2≤n≤10^6。
对于100%的数据,2≤n≤10^12,0≤d≤1000,-1000≤a,b≤1000,保证存
在一种爬山方案合法。
题解
看数据范围大概就知道是个 $O(1)$ 或者 $O(log(n))$ 好题了233
大概有两种思路:
1.首先计算起点与终点间的差值, 然后计算出补齐差值到一跳之内所需要的跳数, 然后把剩余的跳数均分, 均分后的跳数乘以一跳的最大距离再加上补齐后两个端点的高度取个最小值就可以了. 时间复杂度 $O(1)$
2.二分答案, 判断从起点走到答案所需的跳数与从答案走到终点所需的跳数, 在跳数和合法的情况下二分最大值, 时间复杂度 $O(log(n))$
参考代码
这里我写的是第一种 $O(1)$ 的思路
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <iostream> 5 #include <algorithm> 6 7 int main(){ 8 freopen("mountain.in","r",stdin); 9 freopen("mountain.out","w",stdout); 10 long long n,d,a,b; 11 scanf("%lld%lld%lld%lld",&n,&d,&a,&b); 12 n--; 13 if(d==0) 14 printf("%lld ",b); 15 else{ 16 if(a>b) 17 std::swap(a,b); 18 long long dx=b-a; 19 long long cnt=dx/d; 20 long long tmp=(n-cnt)/2; 21 printf("%lld ",std::max(std::max(a,b),std::min(a+(n-tmp)*d,b+tmp*d))); 22 } 23 }