单调队列 hdu2823

Sliding Window

Time Limit: 12000MS   Memory Limit: 65536K
Total Submissions: 48608   Accepted: 14047
Case Time Limit: 5000MS

Description

An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example: 
The array is [1 3 -1 -3 5 3 6 7], and k is 3.

Window position Minimum value Maximum value
[1  3  -1] -3  5  3  6  7  -1 3
 1 [3  -1  -3] 5  3  6  7  -3 3
 1  3 [-1  -3  5] 3  6  7  -3 5
 1  3  -1 [-3  5  3] 6  7  -3 5
 1  3  -1  -3 [5  3  6] 7  3 6
 1  3  -1  -3  5 [3  6  7] 3 7

Your task is to determine the maximum and minimum values in the sliding window at each position.

Input

The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line.

Output

There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values.

Sample Input

8 3
1 3 -1 -3 5 3 6 7

Sample Output

-1 -3 -3 -3 3 3
3 3 5 5 6 7

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <queue>
 4 #include <algorithm>
 5 using namespace std;
 6
 7 int a[1000005],q[1000005],p[1000005],mi[1000005],ma[1000005];
 8 int n,k;
 9
10 void get_min()
11 {
12     int i,j;
13     int head=1,tail=0;
14     for(i=0;i<k-1;i++)
15     {
16         while(head<=tail && q[tail]>=a[i])
17             tail--;
18         q[++tail]=a[i];
19         p[tail]=i;
20     }
21
22     for(;i<n;i++)
23     {
24         while(head<=tail && q[tail]>=a[i])
25             tail--;
26         q[++tail]=a[i];
27         p[tail]=i;
28         while(p[head]<i-k+1)
29         {
30             head++;
31         }
32         mi[i-k+1]=q[head];
33     }
34 }
35
36 void get_max()
37 {
38     int i,j;
39     int head=1,tail=0;
40     for(i=0;i<k-1;i++)
41     {
42         while(head<=tail && q[tail]<=a[i])
43             tail--;
44         q[++tail]=a[i];
45         p[tail]=i;
46     }
47     for(;i<n;i++)
48     {
49         while(head<=tail && q[tail]<=a[i])
50             tail--;
51         q[++tail]=a[i];
52         p[tail]=i;
53         while(p[head]<i-k+1)
54             head++;
55         ma[i-k+1]=q[head];
56     }
57 }
58
59 int main()
60 {
61     int i,j;
62     scanf("%d %d",&n,&k);
63     for(i=0;i<n;i++)
64     {
65         scanf("%d",&a[i]);
66     }
67     get_max();
68     get_min();
69     for(i=0;i<n-k;i++)
70     {
71         printf("%d ",mi[i]);
72     }
73     printf("%d\n",mi[n-k]);
74     for(i=0;i<n-k;i++)
75     {
76         printf("%d ",ma[i]);
77     }
78     printf("%d\n",ma[n-k]);
79     return 0;
80 }

时间: 2024-10-10 16:10:07

单调队列 hdu2823的相关文章

【动态规划】【单调队列】tyvj1305 最大子序和

http://blog.csdn.net/oiljt12138/article/details/51174560 单调队列优化dp #include<cstdio> #include<deque> #include<algorithm> #include<iostream> using namespace std; typedef long long ll; int n,m; ll a[300100],ans; deque<int>q; int

hdu_5884_Sort(二分+单调队列)

题目链接:hdu_5884_Sort 题意: 有n个数,每个数有个值,现在你可以选择每次K个数合并,合并的消耗为这K个数的权值和,问在合并为只有1个数的时候,总消耗不超过T的情况下,最小的K是多少 题解: 首先要选满足条件的最小K,肯定会想到二分. 然后是如何来写这个check函数的问题 我们要贪心做到使消耗最小,首先我们将所有的数排序 然后对于每次的check的mid都取最小的mid个数来合并,然后把新产生的数扔进优先队列,直到最后只剩一个数. 不过这样的做法是n*(logn)2 ,常数写的小

[Vijos 1243]生产产品(单调队列优化Dp)

Description 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器中的任何一台完成,但生产的步骤必须严格按顺序执行.由于这N台机器的性能不同,它们完成每一个步骤的所需时间也不同.机器i完成第j个步骤的时间为T[i,j].把半成品从一台机器上搬到另一台机器上也需要一定的时间K.同时,为了保证安全和产品的质量,每台机器最多只能连续完成产品的L个步骤.也就是说,如果有一台机器连续完

单调队列

先放上luogu的题目链接--滑稽窗口 然后我们再来讲单调队列 单调队列是指这样一种队列:在队列中的元素为单调递增状态或单调递减状态. 例如1 2 3 4 5和9 2 1都是单调队列,但1 2 2 3 4和4 3 4 5就不是单调队列. 但普通队列明显是维持不了单调队列的性质的. 为了维持单调队列的单调性质,我们只好想一些方法.方法就是修改队列的性质.单调队列不仅队头可以出队,队尾也可以出队. 比如说有一个单调队列是 1 3 7 8 现在突然要从队尾进来一个6如果单纯的把6插进队尾的话,那这个队

单调队列 BZOJ 2096 [Poi2010]Pilots

2096: [Poi2010]Pilots Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 819  Solved: 418[Submit][Status][Discuss] Description Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是不行的,于是他找到了你. Input 输入:第一行两个有空格隔开的整数k(0

HDU 3706 Second My Problem First (单调队列)

题意:求给定的一个序列中最长子序列,该子序列的最大值和最小值介于m和k之间. 析:用两个单调队列来维护一个最小值,一个最大值,然后每次更新即可. 代码如下; #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <i

codevs3327选择数字(单调队列优化)

3327 选择数字 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 给定一行n个非负整数a[1]..a[n].现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入描述 Input Description 第一行两个整数n,k 以下n行,每行一个整数表示a[i]. 输出描述 Output Description 输出一个值表示答案. 样例输入 Sample Input 5 2

【NOIP数据结构专项】单调队列单调栈

[洛谷P1901 ]发射站 http://www.luogu.org/problem/show?pid=1901 题目描述 某地有 N 个能量发射站排成一行,每个发射站 i 都有不相同的高度 Hi,并能向两边(当 然两端的只能向一边)同时发射能量值为 Vi 的能量,并且发出的能量只被两边最近的且比 它高的发射站接收. 显然,每个发射站发来的能量有可能被 0 或 1 或 2 个其他发射站所接受,特别是为了安 全,每个发射站接收到的能量总和是我们很关心的问题.由于数据很多,现只需要你帮忙计 算出接收

【单调队列优化DP】BZOJ1855-[Scoi2010]股票交易

[题目大意] 已知第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股. 股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易.同时,在任何时间,一个人的手里的股票数不能超过MaxP. 在第1天之前,有一大笔钱(可以认为钱的数目无限),没有任何股票,求T天之后最多赚到多