单调队列 poj2823,fzu1894

题目链接:http://poj.org/problem?id=2823

用RMQ超时了,我想应该是不会的,看discuss说,之前RMQ过了。

维护两个单调队列。

单调递减的队列,每插入一个时:

超过单调队列长度,左移头指针。

第一个或者符合条件,直接加到后面。

否则,一直退;

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5
 6 using namespace std;
 7
 8 const int N = 1000000 + 5;
 9
10 int n,m;
11 int a[N],q[N];
12
13 void MinQ()
14 {
15     int h=1,t=0;
16     q[1] = 1;
17     for(int i=1;i<=n;i++) {
18         if(i-q[h]==m) h++;
19
20         if(t==h-1||a[i]>a[q[t]]) {
21             t++;
22             q[t] = i;
23         }
24         else {
25             while(t>=h&&a[i]<=a[q[t]])
26             {
27                 q[t] = i;
28                 t--;
29             }
30             t++;
31         }
32         if(i>=m) printf("%d ",a[q[h]]);
33
34     }
35     puts("");
36 }
37
38 void MaxQ()
39 {
40     int h=1,t=0;
41     q[1] = 1;
42     for(int i=1;i<=n;i++) {
43
44         if(i-q[h]==m) h++;
45
46         if(t==h-1||a[i]<a[q[t]]) {
47             t++;
48             q[t] = i;
49         }
50         else {
51             while(t>=h&&a[i]>=a[q[t]])
52             {
53                 q[t] = i;
54                 t--;
55             }
56             t++;
57
58         }
59         if(i>=m) printf("%d ",a[q[h]]);
60
61     }
62 }
63
64 int main()
65 {
66     cin>>n>>m;
67     for(int i=1;i<=n;i++) {
68         scanf("%d",&a[i]);
69     }
70
71     MinQ();
72     MaxQ();
73
74     return 0;
75 }

题目链接:http://acm.fzu.edu.cn/problem.php?pid=1894

和单调递增队列一样。

 1 /*
 2 RunID: 727738
 3 UserID: TreeDream
 4 Submit time: 2017-02-16 00:04:08
 5 Language: C++
 6 Length: 1167 Bytes.
 7 Result: Accepted
 8 */
 9
10 //#include <bits/stdc++.h>
11 #include <iostream>
12 #include <cstdio>
13 #include <algorithm>
14 #include <cstring>
15
16
17 using namespace std;
18
19 const int maxn = 1000000 + 5;
20 int a[maxn];
21 int q[maxn];
22
23 int main()
24 {
25     //freopen("in.txt","r",stdin);
26     int t;
27     scanf("%d",&t);
28
29     while(t--)
30     {
31         char op[10];
32         scanf("%s",op);
33
34         int head = 1,tail = 0;
35
36         q[0] = -1;
37
38         int i=0,j=1;
39         char cmd[10],name[10];
40         int len = 0;
41
42         while(scanf("%s",cmd))
43         {
44             if(strcmp(cmd,"END")==0) break;
45
46             if(cmd[0]==‘C‘)     //插入是有条件的
47             {
48                 scanf("%s",name);
49                 len ++;
50                 scanf("%d",&a[len]);
51                 while(head<=tail&&a[q[tail]]<=a[len])
52                     tail--;
53                 q[++tail] = len;
54             }
55
56             else if(cmd[0]==‘G‘)
57             {
58                 while(head<=tail&&q[head]<=j)
59                     head++;
60                 j++;
61             }
62             else printf("%d\n",head>tail?-1:a[q[head]]);
63         }
64     }
65
66     return 0;
67 }

参考:http://blog.csdn.net/acdreamers/article/details/20911981

时间: 2024-10-30 04:35:04

单调队列 poj2823,fzu1894的相关文章

POJ2823 Sliding Window (单调队列)

POJ2823 Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 38342   Accepted: 11359 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 ve

POJ2823 单调队列

POJ2823 http://poj.org/problem?id=2823 最基础的单调队列,说是数据结构,其实就是一种更新数组数据的方法. 之前还准备用deque,超时了,直接head,tail快得多. 一直把删除队首过期元素写在删除队尾之前,就一直WA,尼玛换一下顺序就好了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 //#define OPEN_FILE 5 using na

单调队列(双端队列) poj2823 hdoj3415 hdoj3530

单调队列及其应用(双端队列) 单调队列,望文生义,就是指队列中的元素是单调的.如:{a1,a2,a3,a4--an}满足a1<=a2<=a3--<=an,a序列便是单调递增序列.同理递减队列也是存在的. 单调队列的出现可以简化问题,队首元素便是最大(小)值,这样,选取最大(小)值的复杂度便为o(1),由于队列的性质,每个元素入队一次,出队一次,维护队列的复杂度均摊下来便是o(1). 如何维护单调队列呢,以单调递增序列为例: 1.如果队列的长度一定,先判断队首元素是否在规定范围内,如果超范

POJ2823 Sliding Window(单调队列)

单调队列,我用deque维护.这道题不难写,我第二次写单调队列,1次AC. ----------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<deque> #define rep(i,r) for(int i=0;i<r;i++) #define clr(x,c) memset

poj2823单调队列

这个裸题,滑动窗口求最大最小值,单调队列来两边,一次单调递增q[s]就是最小值,一次单调递减q[s]就是最大值 cin会超时,解除同步也没用... #include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<cassert> #incl

POJ2823 Sliding Window (单调队列的基本应用)

题目链接: http://poj.org/problem?id=2823 题意: 给定一个长度为n的序列,求每个长度为k的区间的最大值与最小值 分析: 单调队列的基本应用 代码如下: <span style="font-size:14px;">#include <iostream> #include <cstring> #include <cstdio> #include <queue> #include <vector

poj-2823(单调队列)

题意:给你长度位n的数组,问每个长度为m的段的最值: 解题思路:这道题是单调队列的入门题: #include<iostream> #include<algorithm> #include<queue> #include<cstdio> #define maxn 1000100 using namespace std; struct node { int val; int pos; }a[maxn]; int que[maxn]; int mn[maxn];

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

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

转: 单调队列

我们从最简单的问题开始: 给定一个长度为N的整数数列a(i),i=0,1,...,N-1和窗长度k. 要求: f(i) = max{a(i-k+1),a(i-k+2),..., a(i)},i = 0,1,...,N-1 问题的另一种描述就是用一个长度为k的窗在整数数列上移动,求窗里面所包含的数的最大值. 解法一: 很直观的一种解法,那就是从数列的开头,将窗放上去,然后找到这最开始的k个数的最大值,然后窗最后移一个单元,继续找到k个数中的最大值. 这种方法每求一个f(i),都要进行k-1次的比较