2021-7-8 单调队列及其应用
Posted KaaaterinaX
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-7-8 单调队列及其应用相关的知识,希望对你有一定的参考价值。
不是优先队列!不是优先队列!
我是fw呜呜呜!看了好久了!
单调队列是既是单调,同时也符合队列先进先出的特点。(入队顺序在前的元素不能排到入队顺序在后的元素后面,而且队内元素有单调性)
假设要求队列都必须是单调递增的数字,而且入队顺序是固定的:
入队顺序:
1 3 2 4 5
队列:
1
1 3
1 2(重点在这步,当要入队的数字不符合递增的条件,那么就让它持续向前走,并删除其后面的元素。)
1 2 4
1 2 4 5
最基础的例题:
求m区间内的最小值
const int maxn=2e6+7;
int a[maxn];
int dl[maxn];
int idx[maxn];
int le=1,ri=0;
int main()
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cout<<dl[le]<<endl;//队首维护的是合法区间内最小值
while(le<=ri&&a[i]<dl[ri])
//删除不应该出现在队列中的元素(不可能成为答案的元素)
ri--;
dl[++ri]=a[i];//新元素入队
idx[ri]=i;
if(i-idx[le]>=m) le++;//如果区间的左边界不在符合条件,则令队头出队
多重背包的单调队列优化:
//单调队列优化多重背包
const int maxn=2e4+7;
ll last[maxn];
ll now[maxn];
//单调队列
ll q[maxn];
int main()
int N,V;
cin>>N>>V;
for(int i=1;i<=N;i++)
ll v,w,s;
cin>>v>>w>>s;
memcpy(last,now,sizeof last);
for(int j=0;j<v;j++)
int h=1,t=0;//单调队列头与尾
for(int k=j;k<=V;k+=v)
//不能用的队头出队列
if(h<=t&&q[h]<k-s*v)
h++;
//运用队头更新now
if(h<=t)
now[k]=max(last[k],last[q[h]]+((k-q[h])/v)*w);
//不符合就往前移
while(h<=t&&last[q[t]]+(k-q[t])/v*w<=last[k])
t--;
//下标入队列
q[++t]=k;
ll ans=0;
for(int i=0;i<=V;i++)
ans=max(ans,now[i]);
cout<<ans<<endl;
以上是关于2021-7-8 单调队列及其应用的主要内容,如果未能解决你的问题,请参考以下文章