hdu3507斜率優化dp

2021-06-16 13:51:37 字數 1121 閱讀 5552

這題:n可能取500000,o(n^2)就會超時吧,所有只能優化。

注意到這題的動態規劃方程:dp[i]=max(dp[j]+(sum[i]-sum[j])^2+m;

化簡下得 :dp[i]=max(dp[j]+sum[i]^2+sum[j]^2-2*sum[i]*sum[j]);    無法直接用單調佇列優化,i和j不能分開。

假設j比k優

dp[j]+sum[i]^2+sum[j]^2-2*sum[i]*sum[j]即:

dp[j]+sum[j]^2-(dp[k]+sum[k]^2)/(2*dp[j]-2*dp[k])即可以看做是兩個點的斜率小於sum[i],這裡用g[j,k]表示j,k兩點的斜率。

這裡用到兩個結論:

1.g[j,k]2.g[i,j]說明一下:

g[i,j]g[i,j]>sum[i],則g[j,k]>g[i,j]>sum[i];k更優

特別注意:

1.這裡sum[i]是遞增的,g[j,k](斜率)也是遞增的,所以每次不滿足斜率大於sum[i]的點,以後也不會大於某個sum[i],所以要出隊。計算dp[i]時從隊首找最優的,即不滿足g[q[head+1],q[head]]<=sum[i]的點,即找到斜率大於sum[i]的點,並將小於或等於sum[i]的點出隊。等於的情況也是不可以的。

2.每次入隊時要保證斜率的單調遞增性。i入隊,g[i,j]>g[j,k];

下面是**:

#include#include#include#include#include#include#include#define maxn 500005

#define inf 0xfffffff

#define min(a,b) ab?a:b

using namespace std;

int n,m,head,tail;

int sum[maxn],q[maxn],dp[maxn];

int getup(int i,int j)

int getdown(int i,int j)

int main()

head=tail=0;

q[tail++]=0;//將0入隊,因為求斜率時至少有2個點

for(int i=1;i<=n;i++)

{while(head+1

HDU3507 斜率優化dp 入門

解題思路 第一次做斜率優化dp,參考了部落格使原本o n 2 的複雜度變成o n 看完部落格之後,看了一下 發現 中 yj yk xj xk sum i 只要碰到乙個不符合這個條件就用j來算dp i 了。其實是這樣的,因為符合上面那個不等式,代表j在以後都會比k要優,所以可以把k去掉,但是一旦在j的...

HDU3507 斜率優化

r 題意 把n分成任意段 每段中連續 每一段代價 ci m 求總的最小代價 i l作為提醒自己的經驗題,即使再水也要記住坑點 其實是自己被坑的地方 斜率優化裸題 首先定義dp i 表示把前i個處理好的最小代價 dp i min 一看這個轉移就是n 2的,我們來搞成o n 的。h i m sum i ...

hdu 3507 斜率優化

我的第一道斜率優化。就這道題而言,寫出原始的方程 dp i min o n 2 的複雜度肯定超時,要麼優化轉移,要麼重寫方程。斜率優化的思想就是減少不必要的列舉 即不列舉肯定不會成為決策點的j 我們考慮兩個位置p 選擇q比選擇p優 當且僅當 dp q sum i sum q 2 m dp p sum...