首页 > 其他分享 >数据结构1.2

数据结构1.2

时间:2023-03-03 18:55:37浏览次数:50  
标签:1.2 int tt 最小值 队列 hh 区间 数据结构

一、简述

本节介绍一下单调队列及其一些应用。

二、单调队列

单调队列就是队列元素满足单调性的一类数据结构,主要用于解决滑动窗口类的问题,即维护一个区间的最值,在应用时时间复杂度是 \(O(n)\) 的。

一般的,如果我们维护区间的最小值,那么维护的队列是单调递增的;如果是维护区间的最大值,那么队列是单调递减的。

三、例题

1.[AcWing154.滑动窗口]

题目描述

给定一个大小为 \(n≤10^6\) 的数组。

有一个大小为 \(k\) 的滑动窗口,它从数组的最左边移动到最右边。

你只能在窗口中看到 \(k\) 个数字。

每次滑动窗口向右移动一个位置。

以下是一个例子:

该数组为 [1 3 -1 -3 5 3 6 7],\(k\) 为 \(3\)。

窗口位置 最大值 最小值
[1 3 -1] -3 5 3 6 7 3 -1
1 [3 -1 -3] 5 3 6 7 3 -3
1 3 [-1 -3 5] 3 6 7 5 -3
1 3 -1 [-3 5 3] 6 7 5 -3
1 3 -1 -3 [5 3 6] 7 6 3
1 3 -1 -3 5 [3 6 7] 7 3

你的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。

输入格式

输入包含两行。

第一行包含两个整数 \(n\) 和 \(k\),分别代表数组长度和滑动窗口的长度。

第二行有 \(n\) 个整数,代表数组的具体数值。

同行数据之间用空格隔开。

输出格式

输出包含两个。

第一行输出,从左至右,每个位置滑动窗口中的最小值。

第二行输出,从左至右,每个位置滑动窗口中的最大值。

输入样例
8 3
1 3 -1 -3 5 3 6 7
输出样例
-1 -3 -3 -3 3 3
3 3 5 5 6 7
解题思路

这是单调队列的模板题。

以求最小值为例。我们用队列维护一个单调递增的队列。从前往后遍历序列,首先队列非空并且队尾元素大于等于当前元素,那么一直弹出队尾,为什么?因为我们要维护最小值,队列中的元素都在区间内,那么当前元素更小,那么队列中比它大的元素一定不会是二者所在区间的最小值,所以要弹出。然后将当前元素入队。如果说队头元素不在区间内了,那么队头要弹出。最后队头就是就是区间最小值。

最大值类似。

C++代码
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
int n, k;
int q[N], a[N];

int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i ++) 
        scanf("%d", &a[i]);
    int hh = 0, tt = -1;
    for (int i = 1; i <= n; i ++)
    {
        while (hh <= tt && a[q[tt]] >= a[i])
            tt --;
        q[++ tt] = i;
        if (q[hh] + k - 1 < i)
            hh ++;
        if (i >= k) printf("%d ", a[q[hh]]);
    }
    printf("\n");
    hh = 0, tt = -1;
    for (int i = 1; i <= n; i ++)
    {
        while (hh <= tt && a[q[tt]] <= a[i])
            tt --;
        q[++ tt] = i;
        if (q[hh] + k - 1 < i) 
            hh ++;
        if (i >= k) printf("%d ", a[q[hh]]);
    }
    return 0;
}

2.[Daimayuan Online Judge.最大连续区间和]

题目描述

给你 \(n\) 个数字 \(a_1,a_2,...,a_n\) 和两个整数 \(l,r\),你需要在 \(a_1,a_2,...,a_n\) 中选出一段连续的区间满足区间长度 \(∈[l,r]\) 并且区间内的数字的和最大。

请求出满足条件的最大连续区间和。

输入格式

第一行三个整数 \(n,l,r\)。

接下来一行 \(n\) 个整数 \(a_1,a_2,...,a_n\)。

输出格式

输出一行一个数,表示答案。

数据范围

对于 \(100\%\) 的数据,保证 \(1≤l≤r≤n≤10^5,−1000≤a_i≤1000\)。

输入样例
6 2 3
-1 3 -3 4 -5 4
输出样例
4
解题思路

首先看到区间和,那么就要想到前缀和。我们固定 \(s[i]\),也就是 \(\sum\limits_{k=1}^i a[k]\),然后区间长度为 \([l,r]\),那么也就是考虑 \(s[i+l-1]\) 至 \(s[i+r-1]\),那么 \(s[x]\) 也就在这之间,有 \(x\in[i+l-1,i+r-1]\)。我们要在这个区间内找到 \(s[x]\) 的最大值。

C++代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;

int n, l, r;
int a[N], s[N]; 
int q[N], hh = 0, tt = -1;

int main()
{
	scanf("%d%d%d", &n, &l, &r);
	for (int i = 1; i <= n; i ++)
	{
		scanf("%d", &a[i]);
		s[i] = s[i - 1] + a[i];
	}
	int x = l, res = - (1 << 30);
	for (int i = 1; i + l - 1 <= n; i ++)
	{
		while (x <= i + r - 1 && x <= n) 
		{
			while (hh <= tt && s[q[tt]] <= s[x])
				tt --;
			q[++ tt] = x;
			x ++;
		}
		if (q[hh] < i + l - 1)
			hh ++;
		res = max(res, s[q[hh]] - s[i - 1]);
	}
	printf("%d\n", res);
	return 0;
}

3.[Daimayuan Online Judge.覆盖]

题目描述

在一张网格图中,每一列有且仅有一个格子被小蜗涂了色,第 \(i\) 列被涂色的格子的高度为 \(a_i\)。

现在有一块高度为 \(h\) 的长方形幕布(挂在高度 \(x\) 的时候能盖住的高度区间为 \([x−h+1,x]\)),幕布可以在列方向无限延伸(也就是说幕布的宽度可以是任意值)。请问在固定幕布挂的高度后,这块幕布最多可以覆盖住连续多少列的被涂色的格子?

输入格式

第一行两个整数 \(n,h\)。

接下来一行 \(n\) 个整数 \(a_1,a_2,...,a_n\)。

输出格式

输出一行一个数,表示答案。

数据范围

对于 \(100\%\) 的数据,保证 \(1≤n≤10^5,1≤h,a_i≤10^6\)。

输入样例
7 4
1 4 5 3 6 1 4
输出样例
4
解题思路

我们维护一个区间,区间为 \([i,j]\),并且这个区间的最大值和最小值之差小于 \(h\),固定左端点,然后尽可能延伸右端点。区间的最值我们用单调队列来维护。然后左端点变为 \(i+1\),\([i+1,j]\) 肯定是符合条件的,我们继续延伸 \(j\) 即可。注意,要先判断队头是否出队。

C++代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;

int n, h;
int a[N];
int q_max[N], q_min[N];
int hh_max, tt_max = -1;
int hh_min, tt_min = -1;


int main()
{
	scanf("%d%d", &n, &h);
	for (int i = 1; i <= n; i ++)
		scanf("%d", &a[i]);
	int j = 0, ans = 0;
	for (int i = 1; i <= n; i ++)
	{
		if (hh_max <= tt_max && q_max[hh_max] < i)
			hh_max ++;
		if (hh_min <= tt_min && q_min[hh_min] < i)
			hh_min ++;
		
		while (j <= n && (j <= i || a[q_max[hh_max]] - a[q_min[hh_min]] <= h))
		{
			j ++;
			if (j > n) 
				break;

			while (hh_max <= tt_max && a[q_max[tt_max]] <= a[j])
				tt_max --;
			q_max[++ tt_max] = j;
			while (hh_min <= tt_min && a[q_min[tt_min]] >= a[j])
				tt_min --;
			q_min[++ tt_min] = j;
		}
		ans = max(ans, j - i);
	}
	printf("%d\n", ans);
	return 0;
}

标签:1.2,int,tt,最小值,队列,hh,区间,数据结构
From: https://www.cnblogs.com/Cocoicobird/p/17176639.html

相关文章

  • k8s1.26.1集群搭建
    安装containerd和kubeadm,kubelet,kubectl/etc/yum.repo.d/docker-ce.repo内容如下:[docker-ce-stable]name=DockerCEStable-$basearchbaseurl=https://download.do......
  • C/C++ 数据结构使用数组实现队列的基本操作
    //使用数组实现队列#include<iostream>#include<Windows.h>usingnamespacestd;#defineMAXSIZE5//队列的最大容量typedefintDataType;//队列中的元素类型......
  • 两数之和 II - 输入有序数组(数据结构和算法两种实现方式)
    题目:给你一个下标从1开始的整数数组numbers,该数组已按非递减顺序排列,请你从数组中找出满足相加之和等于目标数target的两个数。如果设这两个数分别是numbers[ind......
  • 数据结构1.1
    一、简述本节介绍一下单调栈以及单调栈的一些应用。二、单调栈所谓单调栈,就是具有存储的元素呈现某种单调性的栈。比如:从栈底元素到栈顶元素是单调递减的,就是一个单调......
  • 11.1/2 鼠标显示问题(harib08a)11.2 实现画面外的支持(harib08b)
    11.1鼠标显示问题(harib08a)存在问题:​ 在harib07d中鼠标移动到最右侧后就不能再往右移了解决办法:将if(mx>binfo->scrnx-16){mx=binfo->scrnx-16;}if(......
  • 3月1日至3月2日——数据结构与算法分析阅读笔记,线性表,AI。
    (开头是一些废话啊,最近感觉学习状态不太好,上高数的时候左耳听进去右耳就出来了,有点跟不上,可能是没吃饭的原因,也可能是最近强度有点大了,下午上完课就给自己休息了一下,结果刷......
  • 数据结构与算法之美
    复杂度分析为什么需要时间复杂度?通过统计、监控获得代码的运行时长和占用内存有一定的局限性。测试结果非常依赖测试环境。如在不同的处理器下获得的运行结果不同。......
  • 【ZooKeeper基础-数据结构、服务端/客户端常用命令】
    一、ZooKeeper简介二、ZooKeeper数据结构&命令**1、数据结构**2、服务端常用命令①单机启动命令:./zkServer.shstart②状态查询命令:./zkServer.shstatus③停止服务......
  • 数据结构之单向不循环链表
    链表是一种物理存储结构上非连续、非顺序的线性存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表中的元素(节点)中记录了与其他元素的连接关系,链表的存储方......
  • K8S 1.20 弃用 Docker 评估之 Docker 和 OCI 镜像格式的差别
    背景2020年12月初,Kubernetes在其最新的Changelog中宣布,自Kubernetes1.20之后将弃用Docker作为容器运行时。弃用Docker带来的,可能是一系列的改变,包括不限于:......