题解:P11663 [JOI 2025 Final] 勇者比太郎 2 / Bitaro the Brave 2

· · 题解

upd:

2025.11.22:二分的时间复杂度写错了,感谢 @complete_binary_tree 指出。

@yuruilin2026 和@Hootime 两个大佬认为这是道水题,一眼秒了。

1. 二分(31pts)

二分初始力量值,从题目知道力量初始值 x 范围为 0\le x \le 10^9,时间复杂度则为 O(N^2 \times \log(10^9)),但题目中 N 的范围为 2 \le N \le 5 \times 10^5,所以极端情况过不了。

代码:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define fast_gets ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define open_f_same freopen("data.in", "r", stdin);freopen("data.out", "w", stdout);
#define close_f fclose(stdin);fclose(stdout);
using namespace std;
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch)){
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
inline void write(int x){
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}
int a[514514],b[514514];
int n;
bool cheek(int x){
    for(int start=0;start<n;start++){
        int fight=x;
        bool flag=true;
        for(int i=0;i<n;i++){
            int j=(i+start)%n;
            if(fight<a[j]){
                flag=false;
                break;
            }
            fight+=b[j];
        }
        if(flag==true) return true;
    }
    return false;
}
int main(){
    //fast_gets
    //open_f_same
    n=read();
    for(int i=0;i<n;i++) a[i]=read();
    for(int i=0;i<n;i++) b[i]=read();
    int low=0,hight=1000000000;
    int ans;
    while(low<=hight){
        int mid=(low+hight)/2;
        if(cheek(mid)){
            ans=mid;
            hight=mid-1;
        }else{
            low=mid+1;
        }
    }
    write(ans);
    //close_f
    return 0;
}

2. 加入前缀和预处理和预处理最大值数组

1. 策略:

4. 代码解释

该算法的时间复杂度为 O(N)