ural 1126. Magnetic Storms (单调队列模板题)
ural 1126 题意:n个数,求从第k个元素开始,求每k个元素的最大值(一共求n-k+1次) 思路:单调队列。 单调队列学习链接 其实单调队列挺容易的理解的。。。当时觉得写不明白大概是因为看到的代码写得太丑了2333
说下我的理解:
单调队列的尾端(就是后进入元素的那一端)其实和单调栈类似。
首端加了个元素期限的概念,不断删除“过期”的元素。
所谓过期的元素,对于这道题来说,当我往前移动到第k+1个元素的时候,第1个元素就是过期了的元素,堆答案不会再有贡献。
理论上单调队列中的元素是<元素的期限,元素>的二元组。
而一般元素的"期限"是由下标的位置决定的,而得到下标就可以知道元素。
所以我们实际操作的时候只需要将下标存入单调队列中就行了。
那么查询最大值呢? 队首元素就是最大值。
以及,用到了stl的双端队列deque(double end queue),头文件是#include
由于每次的答案是队首元素,因此设置哨兵而使得队列不为空就使得问题变得繁琐。
所以这里不同于单调栈的写法,我们不设置哨兵,而是.empty()判断双端队列是否为空。
也正是因为这个原因,没有办法像单调栈一样写成for的样子(因为没有哨兵,初始x=dq.front()的时候可能dp中还没有元素,导致RE),而是写成while的样子。。具体见代码。
/* ***********************************************
Author :111qqz
Created Time :2016年08月04日 星期四 23时08分34秒
File Name :code/ural/1126.cpp
************************************************ */
1#include <cstdio>
2#include <cstring>
3#include <iostream>
4#include <algorithm>
5#include <vector>
6#include <queue>
7#include <set>
8#include <map>
9#include <string>
10#include <cmath>
11#include <cstdlib>
12#include <ctime>
13#include <deque>
14#define fst first
15#define sec second
16#define lson l,m,rt<<1
17#define rson m+1,r,rt<<1|1
18#define ms(a,x) memset(a,x,sizeof(a))
19typedef long long LL;
20#define pi pair < int ,int >
21#define MP make_pair
1using namespace std;
2const double eps = 1E-8;
3const int dx4[4]={1,0,0,-1};
4const int dy4[4]={0,-1,1,0};
5const int inf = 0x3f3f3f3f;
6const int N=3E4+7;
7int a[N];
8int f[N];
9int n,k;
10deque<int>dq;
11int main()
12{
13 #ifndef ONLINE_JUDGE
14 freopen("code/in.txt","r",stdin);
15 #endif
16 scanf("%d",&k);
17 n = 0 ;
18 while (scanf("%d",&a[++n])!=EOF)
19 {
20 if (a[n]==-1)
21 {
22 n--;
23 break;
24 }
25 }
26 //for ( int i = 1 ; i <= n ; i++) cout<<"a[i]:"<<a[i]<<endl;
27 dq.clear();
28 for ( int i = 1 ; i <= n ; i++)
29 {
30 while (!dq.empty()&&dq.front()<i-k+1) dq.pop_front(); //不断删除队首过期元素。以第i个元素结尾的连续K个元素的开头位置是i-k+1,在这之前的已经“失效”,因此出队.
31 while (!dq.empty()&&a[dq.back()]<=a[i]) dq.pop_back();//不断删除队尾破坏单调性的元素。能删除的原因是比i早出现并且不比i大的元素一定不会成为答案。
32 dq.push_back(i);
33 // cout<<"dq.size():"<<dq.size()<<endl;
34 //cout<<"i:"<<i<<" "<<dq.front()<<endl;
35 if (i>=k)
36 printf("%d\n",a[dq.front()]);
37 }
38 #ifndef ONLINE_JUDGE
39 fclose(stdin);
40 #endif
41 return 0;
42}