這題: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...