BZOJ 2439: [中山市选2011] 序列

版权声明:本文为一名蒟蒻的原创文章,大神转载的话顺便说个出处呗。 https://blog.csdn.net/cgh_Andy/article/details/78878326

没人写过题解?(其实贴吧那个启发性就够了233

f[i]表示把1~i改为递增的最小代价,g[i]表示把i~n改为递减的最小代价。
不难求出f和g数组(而且他们是满足可减性的)。
然后考虑固定一个中点,左边和右边答案分别是什么
比如说把1~i改成一个倒V的最小代价是
这里写图片描述(2 < j < i)
i~n的也同理啊。
然后发现这个各自的决策是有单调性的,画画图就知道了,然后扫一扫就好..

实在不懂就看代码?(又短又快呢 现在是最快的233

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+3;
char O[1<<14],*S=O,*T=O;
#define gc (S==T&&(T=(S=O)+fread(O,1,1<<14,stdin),S==T)?-1:*S++)
inline int read(){
    int x=0,f=1; char ch=gc;
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=gc;}
    while(ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=gc;}
    return x*f;
}
LL g[N],f[N],L[N],R[N]; int a[N];
int main(){
    int n=read(),i,u;
    for(i=1;i<=n;++i) a[i]=read(); a[0]=-1;
    for(i=1;i<=n;++i) f[i]=f[i-1]+max(a[i-1]-a[i]+1,0);
    for(i=n;i>=1;--i) g[i]=g[i+1]+max(a[i+1]-a[i]+1,0);
    u=2;
    for(i=3;i<n-1;++i){
        while(u<i-1 && max(f[u+1],g[u+1]-g[i])<=max(f[u],g[u]-g[i]) )
            ++u;
        L[i]=max(f[u],g[u]-g[i]);
    }
    u=n-1;
    for(i=n-2;i>2;--i){
        while(u>i+1 && max(g[u-1],f[u-1]-f[i])<=max(g[u],f[u]-f[i]) )
            --u;
        R[i]=max(g[u],f[u]-f[i]);
    }
    LL ans=(1ll<<60);
    for(i=3;i<n-1;++i) ans=min(ans,L[i]+R[i]);
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/cgh_Andy/article/details/78878326