1 条题解

  • 0
    @ 2025-8-24 21:36:06

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar fyfy
    **

    搬运于2025-08-24 21:36:06,当前版本为作者最后更新于2018-09-07 09:38:15,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    听说这题可以n2n^2水过去,

    不过这里介绍一种O(n)的做法。

    f[i]f[i]为第[1,i][1,i]位合并的次数

    pre[i]pre[i]为第[1,i][1,i]位最末尾的数

    jj为满足sum[i]sum[j]>=pre[j]sum[i]-sum[j]>=pre[j]的最大数

    f[i]=f[j]+ij1f[i]=f[j]+i-j-1

    pre[i]=sum[i]sum[j]pre[i]=sum[i]-sum[j]

    显然pre[i]pre[i]越小越好,这样找到一个就可以退出。

    所以可以直接用单调队列优化。

    时间复杂度O(n)O(n)

    代码,注意开long long\texttt{long~long}

    #include <bits/stdc++.h>
    using namespace std;
    typedef int _int;
    #define int long long
    
    const int N=200010;
    int head,tail=1;
    int n,f[N],pre[N],sum[N],q[N];
    
    _int main()
    {
        ios::sync_with_stdio(false);
        cin>>n;
        int x;
        for (int i=1;i<=n;++i)
            cin>>x,sum[i]=sum[i-1]+x;
        for (int i=1;i<=n;++i) {
            while (head+1<tail&&sum[i]>=sum[q[head+1]]+pre[q[head+1]])
                ++head;
            f[i]=f[q[head]]+1;
            pre[i]=sum[i]-sum[q[head]];
            while (head<tail&&sum[q[tail-1]]+pre[q[tail-1]]>sum[i]+pre[i])
                --tail;
            q[tail++]=i;
        }
        cout<<n-f[n];
        return 0;
    }
    
    • 1

    信息

    ID
    1253
    时间
    1000ms
    内存
    125MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者