• 洛谷 P2300 合并神犇


    洛谷

    听说这题可以(n^2)水过去,不过这里介绍一种(O(n))的做法。

    (f[i])为第(1~i)位合并的次数。

    (pre[i])为第(1~i)位最末尾的数。

    (j)为满足(sum[i]−sum[j]>=pre[j])的最大数。

    所以很好推出:

    (f[i]=f[j]+i−j−1~~~~~pre[i]=sum[i]−sum[j])

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

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

    时间复杂度(O(n))

    代码,注意开( exttt{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;
    }
    
  • 相关阅读:
    算法笔记--支配树
    51Nod 1187 寻找分数
    ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer
    ACM-ICPC 2018 徐州赛区网络预赛 A. Hard to prepare
    HDU
    HDU
    Codeforces 1011E
    Codeforces 990D
    Codeforces 989C
    Codeforces 932E
  • 原文地址:https://www.cnblogs.com/fushao2yyj/p/9602751.html
Copyright © 2020-2023  润新知