场上过不去的简单题

I.AT_abc370_f

首先套路的破换成链,然后二分答案 p

对于每一个二分的答案 p,考虑先二分出 fi,0 表示 i 之后第一个满足 j=ifi,0ajpfi,0,然后倍增的设 fi,j 表示 i 之后满足 2j 次上述条件的下标为 fi,j。特殊的若不可以满足则令 fi,j=1

然后考虑枚举起点,直接暴力倍增计算出 k 次操作之后的答案即可。时间复杂度为 O(nlog2n)。代码有点混乱。

const int N=400100,mod=998244353;
int a[N],s[N],n,k,now,nxt[N][20],res;
bool chk(int p){
    memset(nxt,-1,sizeof nxt);
    F(i,1,n+n){
        int l=i,r=i+n-1,best=-2;
        r=min(r,n+n);
        while(l<=r){
            int mid=l+r>>1;
            if(s[mid]-s[i-1]>=p)best=mid,r=mid-1;
            else l=mid+1;
        }
        nxt[i][0]=best+1;
    }
    nxt[n+n+1][0]=n+n+1;
    F(i,1,19)
        F(j,1,n+n+1)
            if(~nxt[j][i-1])
                nxt[j][i]=nxt[nxt[j][i-1]][i-1];
    // F(i,1,n+n)
    //     cout<<i<<": "<<nxt[i][0]<<' '<<nxt[i][1]<<" qwq\n";
    int cnt=0;
    F(i,1,n){
        int x=i;
        G(j,19,0)
            if(k>>j&1){
                x=nxt[x][j];
                if(x==-1||x>i+n)break;
            }
        if(x!=-1&&x<=i+n)
            ++cnt;
    }
    if(cnt)
        res=n-cnt;
    return !!cnt;
}
signed main(){
    cin>>n>>k;
    F(i,1,n)cin>>a[i],s[i]=s[i-1]+a[i];
    F(i,1,n)a[i+n]=a[i],s[i+n]=s[i+n-1]+a[i];
    int l=1,r=s[n],best=-1;
    while(l<=r){
        int mid=l+r>>1;
        if(chk(mid))best=mid,l=mid+1;
        else r=mid-1;
    }
    cout<<best<<' '<<res<<'\n';
}

posted @   yhbqwq  阅读(101)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
点击右上角即可分享
微信分享提示