hihocoder #1529 : 不上升序列
阿新 • • 發佈:2018-07-15
表示 ret pre pop 需要 存在 scrip esc int 的位置,折線是不會穿過 \(x\) 軸的,所以肯定存在斜率為 \(0\) 的位置)
Description
給定一個長度為 n 的非負整數序列 a[1..n]。
你每次可以花費 1 的代價給某個 a[i] 加1或者減1。
求最少需要多少代價能將這個序列變成一個不上升序列。
Solution
容易想到一個 \(dp\),設 \(f[x][i]\) 表示前 \(x\) 個數,最小的數不小於 \(i\) 的最小代價
\(f[x][i]=f[x-1][i]+|a_x-i|\)
其實這是兩條折線合並的過程,\(|a_x-i|\) 是一條以 \(a_x\) 為拐點的折線,且兩條直線的斜率分別為 \(1,-1\)
對於 \(f[x][i]\) 也是一條折線或直線,顯然在拐點處的解是最優的(也就是斜率變成 \(0\)
我們分兩種情況合並這兩條折線
觀察圖片發現:新圖也就是把原圖中的兩條折線的每一段的斜率分別相加
這裏的拐點也就是使得斜率發生改變的地方,因為斜率發現改變的地方都有可能成為斜率為 \(0\) 的那個拐點
用堆維護拐點的橫坐標就可以了
#include <bits/stdc++.h> using namespace std; const int N=5e5+10; priority_queue<int>Q; int main() { freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); int n,x;long long ans=0; cin>>n; for(int i=1;i<=n;i++){ scanf("%d",&x); x=-x;Q.push(x); if(Q.top()>x)ans+=Q.top()-x,Q.pop(),Q.push(x); } printf("%lld\n",ans); return 0; }
hihocoder #1529 : 不上升序列