只能說是**美如畫。(當然我是指內在邏輯不是我的**風格,隊長看到要理解哈,啊哈哈哈哈哈哈哈哈)
正常思路咯,f[i]=f[j]+max(a[j+1],a[j+2]....a[i]),列舉j,顯然硬來會超時,所以需要有乙個單調佇列來時時把最大值盡快弄出來並且需要一些剪枝;
剪枝條件有兩個,乙個是和不能超過m,乙個是顯然f[i]是個非嚴格遞增序列,根據這兩個條件剪枝;
則建立單調佇列,每當插入新的i時將前面先把和小於等於m的條件做好,然後對於j然後就看**吧
1 #include 2 #include 3 #include4 #include 5 #include 6 #include 7 #include 8 #include 9
using
namespace
std;
1011 typedef long
long
ll;12
13const
int n=100005;14
const
long
long inf=1000000000ll;
15int
n;16
ll m;
17ll a[n],f[n];
18ll solve()
29while(l<=r&&a[q[r]]<=a[i]) r--;//
等於號是細節
30 q[++r]=i;
31while(l<=r&&q[l]<=k) l++;
32ll tmp;
33int kk=k;
34 f[i]=inf;
35//
cout<36
for ( j=l; j<=r; j++) //
佇列優化後的dp過程,加入過程保證了單調佇列中元素是遞減的
3743
//f[i]=tmp;
44//
cout<45}46
if(fg)
47return -1;48
else
49return
f[n];50}
51int
main()
52
再加一種用multiset的
#include #include#include
#include
#include
#include
#include
#include
using
namespace
std;
typedef
long
long
ll;const
int n=100005
;const
long
long inf=1000000000ll;
intn;
ll m;
ll a[n],f[n];
multiset
q1;ll solve()
while(l<=r&&a[q[r]]<=a[i])//
等於號是細節
q[++r]=i;
if(l1]]+a[i]);
while(l<=r&&q[l]<=k)
ll tmp=*(q1.begin());
f[i]=f[k]+a[q[l]];
if(tmptmp;
//f[i]=tmp;
//cout<}
if(fg)
return -1
;else
return
f[n];
}int
main()
POJ3017 單調佇列
交的時候沒什麼信心會ac,結果ac了,挺高興的。如果之前能確定演算法沒問題,應該自信點 不熟練還是 題解 先得dp方程 f i f j max x j 1 x j 2 x i 其中j include include include using namespace std typedef int64 ...
poj 3017(單調佇列)
想了半天終於是看的題解,網上的題解好像都是出自一人之手,寫的都一毛一樣,令人窒息。建了乙個遞減的佇列,具體很難講的清,又不想複製別人的講解,就這樣吧。include include include include include include include define ls 2 rt defi...
POJ 3017 單調佇列 最值優化 的動態規劃
令f i 表示前i個數按照題目要求的最小的和 則必然有f i min f j max a j 1 a j 2 a i 其中j i,j的位置還得滿足題目中m 的限制 由於a陣列都是大於0的,所以可以發現f必然是非遞減的。設a j 1 a j 2 a i 中值最大的下標為k 設x為 j 1,k 的任意乙...