题解-P6040 「ACOI2020」课后期末考试滑溜滑溜补习班

  • 题目意思

题目较长,不便于描述

这道题目就是考察了一道基础的单调队列优化,以及化柿子的方法。

,暴力

表示到的最小花费精力,转移 即可

if(n<=1000)
{
    memset(f,127/3,sizeof(f));
    f[1]=a[1];
    for ( int i=2;i<=n;i++ ) 
        for ( int j=max(1ll,i-X);j<i;j++ ) 
            f[i]=min(f[i],f[j]+K+(i-j-1)*D+a[i]);
    printf("%lld\n",f[n]);
    exit(0); 
}

,单调队列优化

对于上述柿子我们可以进行移项合并得到:

到这里我们很容易想到用单调队列去维护单减即可,于是就是单调队列的基本操作了。

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e7+5;

int n,m,K,D,X,type,a[N],f[N],q[N],Seed;

inline int read() 
{
    int sum=0; char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) 
        sum=sum*10+(ch^48),ch=getchar();
    return sum;
}

inline int rnd () 
{
    static const int MOD = 1e9;
    return Seed=(1ll*Seed*0x66CCFF%MOD+20120712)%MOD;
}

inline void Sub()
{
    for ( int i=1;i<=n;i++ ) a[i]=read();
    if(n<=1000)
    {
        memset(f,127/3,sizeof(f));
        f[1]=a[1];
        for ( int i=2;i<=n;i++ ) 
            for ( int j=max(1ll,i-X);j<i;j++ ) 
                f[i]=min(f[i],f[j]+K+(i-j-1)*D+a[i]);
        printf("%lld\n",f[n]);
        exit(0); 
    }
    f[1]=a[1];
    int head=1,tail=1;
    q[1]=1;
    for ( int i=2;i<=n;i++ ) 
    {
        while(head<=tail&&i-q[head]>X) head++;
        f[i]=f[q[head]]+K+(i-q[head]-1)*D+a[i];
        while(head<=tail&&f[q[tail]]-q[tail]*D>=f[i]-i*D) tail--;
        q[++tail]=i;
    }
    printf("%lld\n",f[n]);
    exit(0);
}

inline void Sub1()
{
    Seed=read();
    for ( int i=1;i<=n;i++ ) a[i]=rnd();
    f[1]=a[1];
    int head=1,tail=1;
    q[1]=1;
    for ( int i=2;i<=n;i++ ) 
    {
        while(head<=tail&&i-q[head]>X) head++;
        f[i]=f[q[head]]+K+(i-q[head]-1)*D+a[i];
        while(head<=tail&&f[q[tail]]-q[tail]*D>=f[i]-i*D) tail--;
        q[++tail]=i;
    }
    printf("%lld\n",f[n]);
    exit(0); 
}

signed main() 
{
    n=read();
    K=read();
    D=read();
    X=read();
    type=read();
    if(!type) Sub();
    else Sub1();
    return 0;
}
/*
10 30630 56910 2 0
7484 99194 86969 17540 29184 68691 91892 81564 93999 74280 

717318
*/