一个题解
Immortal_Deity · · 题解
提供一种不一样的二分,不用前缀和 (〃´-ω・)/。
显然初始力量是单调性的,力量越多显然越能打,所以可以考虑二分。
思路 (不很清楚谅解一下)
这个二分的 check 比较特殊,不用把怪物看成环,下面我们以第二个样例为例,来讲述一下这个方法(这个 check 我不太会讲所以我举例):
怪物强度:
- 初始为
3
这个时候我们不妨假设我们的初始力量为
我们就从第一个位置开始,怪物强度只有 新开一个存档,从第三个怪开始打,剩下两个怪物秋后算账。\
很顺利,下面三个怪物都清掉了,我们回到开头,发现剩下的怪也能清掉,那么这就说明了初始力量为
- 初始为
1
再假设初始力量为
我们重复上面的流程,发现没有一种起点能打到底,所以
- 初始为
2
在最后一个怪开始能打到底,但回去从开头打的话会有打不掉的怪,,所以
code
如果还有不理解的地方可以看看这里:
:::success[代码]
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5 * 114514;
int n;
int a[N];
int b[N];
bool check(int x){
int rj = 0;
int sum = 0;
for(int i = 1;i <= n;i ++ ){
if(x >= a[i]){
int j;
int tmp = x;
for(j = i;j <= n;j ++ ){
if(tmp >= a[j]){
tmp += b[j];
}
else{
break;
//打不过,重新找起点
}
}
if(j > n){
rj = i;
sum = tmp;
//我找到起点了
break;
}
i = j - 1; // 不是我能打过的怪,直接跳过
}
}
if(rj == 0) return 0; //打不到底
for(int i = 1;i < rj;i ++ ){
if(sum < a[i]) return 0;
sum += b[i];
}
return 1;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for(int i = 1;i <= n;i ++ ){
cin >> a[i];
}
for(int i = 1;i <= n;i ++ ){
cin >> b[i];
}
int lft = 0;
int rgt = 1e9 + 5;
int ans = rgt;
while(lft <= rgt){
int mid = lft + rgt >> 1;
//二分初始力量
if(check(mid)){
rgt = mid - 1;
ans = mid;
}
else{
lft = mid + 1;
}
}
cout << ans << endl;
return 0;
}
:::