单调队列的应用
来源:互联网 发布:error 1130 mysql 编辑:程序博客网 时间:2024/05/22 15:35
一、
窗口位置 最小值 最大值 [1 3 -1] -3 5 3 6 7 -13 1 [3 -1 -3] 5 3 6 7 -33 1 3 [-1 -3 5] 3 6 7 -35 1 3 -1 [-3 5 3] 6 7 -35 1 3 -1 -3 [5 3 6] 7 36 1 3 -1 -3 5 [3 6 7]37
你的任务是得到滑动窗口在每个位置时的最大值和最小值。
第一行包括n和k,分别表示数组的长度和窗口的大小。
第二行包括n个数字。
第一行包括窗口从左至右移动的每个位置的最小值。
第二行包括窗口从左至右移动的每个位置的最大值。
8 31 3 -1 -3 5 3 6 7
-1 -3 -3 -3 3 33 3 5 5 6 7
构造一个单调队列并进行维护。以求最小值为例,构造一个队列存储元素的下标,每有一个新的元素,如果队列为空直接插入,若非空,则从队尾开始比较将大于插入元素的都清除,然后插入新元素作为备选。(新元素的下标比旧元素靠后,所以旧元素中比新元素值大的就失去了作为备用最小值的意义,可以清除掉不管)同时,若队首元素超出范围则清除。求最大值的也类似。
e.g . 拿样例来说,元素存放在arr[]中,构造队列que{}。n为8,k为3.
插入扫过第一个元素,直接把下标放入得到que{0}。第二个元素3>1,放入下标后的到que{0,1}.第三个元素-1<1,将数值1和3的下标清除 ,放入下标后得到que{2},这是输出arr[2].第四个元素-3<-1,得到que{3},输出arr[3],第五个5>-3.得到que{3.4}....
#include <iostream>#include <cstdio>using namespace std;int arr[1000000];int que[1000000];int head = 0, rear = -1;int empty(){ return rear < head;}int main(){ int n, k; scanf("%d%d", &n, &k); for(int i = 0; i < n; i++) scanf("%d", &arr[i]); int i = 0; //最小值 while(i < n){ while(arr[i] <= arr[que[rear]] && rear >= head) rear--; //找到新插入元素的位置,并清除大于该元素的旧元素 que[++rear] = i; //插入新元素的下标 while(!empty() && que[head] < i-k+1) head++; //清除队首超出范围的元素 if(i >= k-1) printf("%d ", arr[que[head]]); //输出队首(最小值) i++; } printf("\n"); i = head = 0; rear = -1; while(i < n){ while(arr[i] >= arr[que[rear]] && rear >= head) rear--; que[++rear] = i; while(!empty() && que[head] < i-k+1) head++; if(i >= k-1) printf("%d ", arr[que[head]]); i++; } return 0;}
二、
农夫John 的N(1 ≤ N ≤ 80,000)只奶牛中,有一些也许正在经历发型糟糕的一天。每只奶牛对自己乱糟糟的发型都有自知之明,农夫John想知道所有奶牛能看到其他奶牛头顶的数量之和。
任意奶牛i身高记为 hi (1 ≤ hi ≤ 1,000,000,000),所有奶牛面向东方(本题示意图的右面)依次站成一条线。因此,奶牛i能够看到在它前面的(奶牛i+1,i+2…)所有身高比它低的奶牛,直到被一头比它高的奶牛挡住
考虑如下的例子:
== == - = Cows facing right ->= = == - = = == = = = = =1 2 3 4 5 6
奶牛#1 可以看见奶牛#2, 3, 4的头顶
奶牛#2 无法看到任何奶牛的头顶
奶牛#3可以看见奶牛#4的头顶
奶牛#4无法看到任何奶牛的头顶
奶牛#5可以看见奶牛#6的头顶
奶牛#6无法看到任何奶牛的头顶!
用ci表示奶牛i能够看到头顶的奶牛个数;请计算c1 至cN的和。对于上面这个例子,其和为:3 + 0 + 1 + 0 + 1 + 0 = 5。
第2行至N+1行:第i+1行包含一个整数,表示奶牛i的高度
610374122
5
这道题目跟上一道类似,可以通过维护一个单调递减队列实现。构造一个单调递减队列存储高度,每次插入一个新元素时,清除比该元素小的元素(因为高度小被当前奶牛挡住了,不用再计算了),该元素作为队尾元素,此时排在该元素前面的都是比他高的都能看见他,所以ans += rear-head;
#include <iostream>using namespace std;int que[80000];int head = 0, rear = -1;int main(){ int n, input; long long ans = 0; cin >> n; while(n--){ cin >> input; while(rear >= head && input >= que[rear]) rear--; //清除矮的 que[++rear] = input; //插入 ans += rear - head; //统计 } cout << ans << endl; return 0;}
- 单调队列的应用
- 单调队列的应用
- 单调队列的应用
- HDU3530 单调队列的应用
- 浅谈单调队列的应用
- 单调队列的实现与应用
- 单调队列应用
- 单调队列 及其应用
- 单调队列及其应用
- 单调队列理解及应用
- Buy Tickets hoj 单调队列优化DP的简单应用
- Sliding Window poj 单调队列的简单应用
- POJ2823 Sliding Window (单调队列的基本应用)
- 单调队列在滑动最小值方面的应用
- 单调队列的原理
- 单调队列的学习
- 单调队列的学习 pku2823
- poj2823,典型的单调队列
- js 控制在关闭ie的提醒
- 20141001 【 高精度 】 2014-上海区域赛-网络预选赛 hdoj 5047 Sawtooth
- windows下搭建Eclipse+android4.0开发环境
- 【HDU 5052】Yaoge’s maximum profit【树链刨分】
- Android中的布局优化方法
- 单调队列的应用
- ios storyboard 视图跳转
- 面试-斐波那契数列
- 大学(一)
- Harvard statistics 110, video 1 note(probability & counting)
- 数据类型的内存量
- 2005的表达
- 结构和大类
- Spring 标签引入和数据库连接问题