Educational Codeforces Round 158 (Rated for Div. 2)D

题意:

思路:维护前后缀最大值(选某个点作为起点的时候只考虑一侧的最大值),因为只能连续清除,那么考虑枚举i,最大值只能出现在3种情况:

1.本身

2.把i以及左侧清理完,加上sufi+1,最大值产生在右侧

3.把i以及右侧清理完,加上prei-1,最大值产生在左侧

cpp 复制代码
#include<bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
const int N=1e6+10;
const int mod=998244353;
vector<int>pm;
int judge[N],nm[N],inv[N];
int Log2[N];
int kmi(int a,int b){
    int res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
void init(){
    nm[0]=inv[0]=1;
    for(int i=1;i<=1e6;i++){
        nm[i]=nm[i-1]*i%mod;
        inv[i]=kmi(nm[i],mod-2);
    }
}
void euler(int n){
    judge[1]=1;
    for(int i=2;i<=n;i++){
        if(!judge[i]){
            pm.push_back(i);
        }
        for(int j=0;pm[j]*i<=n;j++){
            judge[pm[j]*i]=1;
            if(i%pm[j]==0) break;
        }
    }
}
int C(int a,int b){
    return nm[a]*inv[a-b]%mod*inv[b]%mod;
}
// struct nod{
//     int p,val;
//     bool operator<(const nod &b)const{
//         return val>b.val;
//     }
// };
//维护单边最大值,枚举i,假设删除掉i以及左边所有元素
void solve(){
    int n;cin>>n;
    vector<int>a(n+10),pre(n+10),suf(n+10);
    for(int i=1;i<=n;i++) cin>>a[i];
    int ans=1e18;
    for(int i=1;i<=n;i++){
        pre[i]=max(pre[i-1]+1,a[i]);
    }
    for(int i=n;i>=1;i--){
        suf[i]=max(suf[i+1]+1,a[i]);
    }
    for(int i=1;i<=n;i++){
        int mx=max({a[i],suf[i+1]+i-1,pre[i-1]+n-i+1});
        ans=min(ans,mx);
    }
    cout<<ans;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);
    // for(int i=2;i<=1e6;i++){
    //     Log2[i]=Log2[i/2]+1;
    // }
    int T=1;//cin>>T;
    while(T--) solve();
    return 0;
}