倍增dp太難啦心情好再回去做
poj1821 先讓工匠按s排序,f[i][j]表示列舉到第i個工匠塗了j個木板(注意第j個木板不一定要塗)
那麼f[i][j]可以直接繼承f[i-1][j]和f[i][j-1]
此外 f[i][j]=max(j-l[i]+1<=k<=s[i])
按照單調佇列運用的思想,維護f[i-1][k-1]-k*p的最大值
#include#includepoj1821#include
#include
#include
#include
using
namespace
std;
struct nodea[110
];bool cmp(node n1,node n2)
int f[110][21000
];int h,t,q[21000
];int
main()
for(int j=1;j1][j],f[i][j-1
]);
for(int j=a[i].s;j<=m;j++)
}printf(
"%d\n
",f[n][m]);
return0;
}
poj3017 神題(其實還好吧)
設f[i]表示1~i的最小值,f[i]=min(∑(k=j+1~i)a[k]<=m)
然而,可以證明的是,可能成為最優決策的j,一定是j+1~i的最大值,或者是滿足∑(k=j+1~i)a[k]<=m最小的j
那麼就可以維護乙個a[j]遞減的單調佇列,但是f[j]+max(j+1~i)(a[k])是不單調的,要用set把值記錄
#include#includepoj3017#include
#include
#include
#include
#include
using
namespace
std;
typedef
long
long
ll;int a[110000],q[110000
];ll f[
110000
];multiset
s;int
main()
}int tp=1;ll sum=0
;
int h=1,t=0
;
for(int i=1;i<=n;i++)
q[++t]=i;
if(h1]]+a[q[t]]);
while(h<=t&&tp>q[h])
f[i]=f[tp-1]+a[q[h]];
if(hs.begin());
}printf(
"%lld\n
",f[n]);
return0;
}
hdu2191 (純粹是給單調佇列維護多重揹包找個例題)
把乙個數拆成u+p*v的形式,f[u+p*v]=max(p-c<=k<=p-1)
維護下f[u+k*v]-k*w
#include#includehdu2191#include
#include
#include
#include
using
namespace
std;
int f[110],q[110
];int
main()
for(int p=li;p>=0;p--)}}
}int ans=0
;
for(int i=1;i<=m;i++)ans=max(ans,f[i]);
printf(
"%d\n
",ans);
}return0;
}
單調佇列 優化DP
佇列元素保持單調遞增 減 而保持的方式就是通過插隊,把隊尾破壞了單調性的數全部擠掉,從而使佇列元素保持單調。單調佇列的作用 優化dp。許多單調佇列優化的dp可以使複雜度直接降維,下面就以最簡單的一道題為例 在某兩座城市之間有 n 個烽火台,每個烽火台發出訊號都有一定代價。為了使情報準確地傳遞,在連續...
單調佇列優化dp
形如f i max wi的問題都可以用單調佇列優化。例題 板題 注意乙個地方 求完所有的f後 ans不是f n 而是後面的一段字尾的f 注意字尾的左端點。很顯然是rmq問題 計算字首和sum i 對於固定的右端點 i,我們想讓答案最大等價於max,可以用個單調佇列維護。但是隨便乙個資料結構直接on ...
DP 單調佇列優化
使用單調佇列優化的題目具有這樣的特點,他需要我們維持一段區間內的某個最優值,這個區間是隨著遍歷的順序變化的,但是其變化一定具有這樣的特性,也即維持的區間左右端點一定是單調遞增的,而不能出現回流的現象,否則我們在維持佇列單調性過程中剪枝的資料可能是新的區間中的最大值。維持區間最優值的方法有很多,例如靜...