单调队列优化

滑窗

题目描述

有一个长为 n 的序列 a,以及一个大小为 k 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

一开始想到的方法是每滑一次,就在这个范围内寻找一次最小值和最大值

但这样很显然会t

所以才会想到单调队列

但是单调队列不会定义一个队列

单调队列是一个数组

存入一个最大值和一个最小值

然后与每次滑到的值进行比较

如果比队尾元素小(大)就放到队尾

如果反之就把队尾元素出队知道符合条件为止

注意队中存入的不是值而是下标

然后就没了

完整代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int n,k;
int q[N],e[N],dp[N];
int head,tail;
int res; 
signed main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>e[i];
		e[i]+=e[i-1];
	}
	for(int i=1;i<=n;i++)
	{
		while(head<=tail&&q[head]+k<i)
	    head++;
		while(head<=tail&&dp[i-1]-e[i]>=dp[q[tail]-1]-e[q[tail]])
		tail--;
		dp[i]=max(dp[i-1],dp[q[head]-1]+e[i]-e[q[head]]);
		q[++tail]=i;
	}
	cout<<dp[n];
	return 0;
}

封面是本人的洛谷头像,

磷叶石好脆弱我好推

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值