[洛谷]P1886 滑动窗口

本文介绍使用单调队列解决滑动窗口中求最大值和最小值的问题,通过双遍历策略,分别构建单调递增和单调递减队列,高效找到指定窗口内的最值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

题目描述

给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数

题目解析

用单调队列来完成

维护好一个正确的单调队列后,队头就是当前区间的最大值或最小值

代码

#include<cstdio>
#define N 10000005
using namespace std;
int n,m,h=1,t=1;
int a[N],list[N];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	 scanf("%d",&a[i]);
	list[1]=1;
	for(int i=1;i<=n;i++)
	{
	  while(h<=t&&a[list[t]]>=a[i]) t--;//删尾 
	  list[++t]=i;//进队 
	  while(i-list[h]>=m) h++;//去头 
	  if(i>=m) printf("%d ",a[list[h]]);//最小值在队头 
	}//单调递增 
	printf("\n");
	h=1;t=1;
	list[1]=1;//初始化 
	for(int i=1;i<=n;i++)
	{
	  while(h<=t&&a[list[t]]<=a[i]) t--;//删尾 
	  list[++t]=i;//进队 
	  while(i-list[h]>=m) h++;//去头 
	  if(i>=m) printf("%d ",a[list[h]]);//最大值在队头 
	}//单调递减 
}
洛谷题目 P3020 通常与“检查牛的身份证号”(Bessie’s ID)相关,其主要内容是根据一定的规则判断一个给定的数字序列是否满足特定条件。以下是与该题相关的常见解题思路和讨论: ### 解题思路 1. **问题分析**: - 输入一个整数数组,表示牛的身份证号的每一位。 - 需要根据题目要求检查是否存在某些连续的子序列,满足特定条件,例如总和为某个值或满足某种模式。 2. **算法选择**: - 对于此类问题,可以采用前缀和法来高效计算子数组的和,从而减少重复计算。 - 如果涉及查找特定模式的子序列,可能需要滑动窗口技巧或哈希表辅助记录状态。 3. **实现细节**: - 使用前缀和时,需要注意初始化和边界情况处理。 - 若题目中涉及模运算,则需考虑负数取模的情况,并适当调整结果。 4. **示例代码**: ```cpp #include <iostream> #include <unordered_map> using namespace std; int main() { int n, target_sum; cin >> n >> target_sum; int arr[n]; for (int i = 0; i < n; i++) { cin >> arr[i]; } // 前缀和数组 long long prefix_sum = 0; unordered_map<long long, int> sum_count; sum_count[0] = 1; // 初始化前缀和为0的情况 long long count = 0; for (int i = 0; i < n; i++) { prefix_sum += arr[i]; if (sum_count.find(prefix_sum - target_sum) != sum_count.end()) { count += sum_count[prefix_sum - target_sum]; } sum_count[prefix_sum]++; } cout << count << endl; return 0; } ``` 5. **易错点**: - 忽略前缀和为0的情况会导致初始条件错误。 - 在涉及大数的情况下,要注意数据类型的选择以避免溢出。 - 滑动窗口方法需要特别注意窗口大小调整的逻辑。 6. **优化建议**: - 如果题目允许,可以通过空间换时间的方式使用哈希表加速查询。 - 对于模运算,可以在每次计算前缀和时对目标值取模,以减少存储空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值