Warning: session_start(): open(/tmp/sess_0b9513dd2dd5e5ac0995428dea3179a0, O_RDWR) failed: No space left on device (28) in /data/wiki/inc/init.php on line 239

Warning: session_start(): Failed to read session data: files (path: ) in /data/wiki/inc/init.php on line 239

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/auth.php on line 430

Warning: mkdir(): No space left on device in /data/wiki/lib/plugins/dw2pdf/vendor/mpdf/mpdf/src/Cache.php on line 19
Temporary files directory "/data/wiki/data/tmp/dwpdf/813/" is not writable

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/actions.php on line 38

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/lib/tpl/dokuwiki/main.php on line 12
2020-2021:teams:legal_string:dp的优化 [CVBB ACM Team]

用户工具

站点工具


2020-2021:teams:legal_string:dp的优化

dp的优化

一、单调队列优化

单调队列优化,可以降低诸如$dp[i]=max\{dp[j]\}+C[i](1\le j <i)$这样的动态转移方程的时间复杂度。主要的原理就是利用一个单调队列来维护$dp[i]$的最值。

一道例题

洛谷p2627

我们不难写出动态转移方程$dp[i]=\left\{\begin{aligned} sum[i],i\le k\\max\{dp[j-1]+sum[i]-sum[j]\}(i-k \le j\le i,i>k)\end{aligned}\right.$

答案为$ans=max\{dp[i]\}$

但是时间复杂度为$O(nk)$,显然会超时

注意到$sum[i]$可以直接提出,即$dp[i]=max\{dp[j]\}+sum[i]$,所以我们只需用一个单调队列来维护$dp[i]$的最值,复杂度可以降低为$O(n)$

代码

#include <stdio.h>
#include <iostream>
using namespace std;
int n,k;
long long e[100001];
long long dp[100001];
long long sum[100001];
int q[100001];
int front=0,tail=1;
long long a(int now)
{
    return dp[now-1]-sum[now];
}
int main()
{
    scanf("%d %d",&n,&k);
    int rec=0;
    for (int i=1;i<=n;i++)
    {
        scanf("%lld",&e[i]);
        sum[i]=sum[i-1]+e[i];
    }
    for (int i=1;i<=n;i++)
    {
    while (front<=tail&&q[front]<i-k)
    front++;    
    dp[i]=a(q[front])+sum[i];
    while (front<=tail&&a(q[tail])<=a(i))
    tail--;
    q[++tail]=i;
    }
    long long ans=0;
    for (int i=1;i<=n;i++)
    ans=max(ans,dp[i]);
    printf("%lld",ans);
    return 0;
}

练习

2020-2021/teams/legal_string/dp的优化.1590914667.txt.gz · 最后更改: 2020/05/31 16:44 由 admin