P8775 [蓝桥杯 2022 省 A] 青蛙过河 题解
题目链接:
有
小青蛙每次跳跃必须落在一块石头或者岸上,每次从一块石头起跳,这块石头的高度就会下降
小青蛙一共需要去学校上
请问小青蛙的跳跃能力至少是多少才能用这些石头上完
跳回来和跳到对岸是没有区别的,所以题目可以看作有
不难想到二分
难点在于 check 函数上,如何判断某个跳跃能力是否能够使
容易发现,任意一个长度为
在这
这样描述可能不是很好理解,我们来模拟一下青蛙跳跃的过程:
-
刚开始,所有青蛙都跳出一步,此时
2x 只青蛙均在区间[1,y] 中。 -
紧接着,处于石头
1 上的所有青蛙跳到区间[2,y+1] 中,由于每个区间的高度和都\geq 2x ,所以区间[2,y+1] 一定能容下这些青蛙。 -
之后青蛙们就可以以类似的方式跳到
[3,y+2], [4,y+3],\dots 一直到[n-y,n-1] ,然后就可以一步到达对岸。
故每个区间高度和
有了这个性质之后,check 函数就很好写了,使用前缀和快速计算出每个区间的高度和即可。
#include <bits/stdc++.h>
#define i64 long long
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define per(i, a, b) for (int i = (a); i >= (b); i--)
using namespace std;
const int N = 1e5 + 5;
int n, x;
i64 arr[N], sum[N];
bool check(int y) {
rep(i, y, n - 1) if(sum[i] - sum[i - y] < 2 * x) return false;
return true;
}
int main() {
cin >> n >> x;
rep(i, 1, n - 1) {
cin >> arr[i];
sum[i] = sum[i - 1] + arr[i];
}
int l = 1, r = n;
while(l < r) {
int mid = (l + r) / 2;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout << r << endl;
return 0;
}