hihoCoder Challenge 29 D. 不上升序列【動態規劃+折線+堆】

題目大意:

給出一個整數序列,可以花費1的代價把一個數+1或­1,求把它變成不上升序列的最小代價。n<=500000;

解題思路:

fi(x) 爲前個數,調整出最大值不超過 x 的最小代價,那麼 fi 是一條不升的折線
考慮轉移 fi(x)=minyxfi1(y)+|aiy|
這實際上是兩條折線合併一下 我們討論兩者的位置關係
先加一個下凸折線,再取個前綴min 。
取前綴min,就是把斜率>=1的部分刪掉,實現的話只需要在堆中記下所有的折點。
附一張題解的圖方便理解:
這裏寫圖片描述

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}
priority_queue<int>q;
int main()
{
    //freopen("lx.in","r",stdin);
    int n=getint(),x;ll ans=0;
    for(int i=1;i<=n;i++)
    {
        x=-getint();q.push(x);
        if(q.top()>x)ans+=q.top()-x,q.pop(),q.push(x);
    }
    cout<<ans<<'\n';
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章