poj2823 Sliding Window

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

 题意:

  一个长度为n的序列上有一个长度为k的滑窗从左向右滑动,问每个时刻滑窗内最小值和最大值。

  题解:

  我们考虑单调队列。

  对于维护最小值,我们维护一个单调递增的序列。新加入一个数时,弹出队尾比他大的数(因为这些数即比他大,又比他靠前,对于后面的区间来说总是不如新加入的数优)。在队首弹出(在序列中编号<该数在序列中编号-k)的数。然后记录队首即该滑窗内最小值。

  最大值同理维护一个单调递减的序列即可。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<deque>
#define LL long long
#define RI register int
using namespace std;
const int INF = 0x7ffffff ;
const int N = 1e6 + 10 ;

inline int read() {
    int k = 0 , f = 1 ; char c = getchar() ;
    for( ; !isdigit(c) ; c = getchar())
      if(c == '-') f = -1 ;
    for( ; isdigit(c) ; c = getchar())
      k = k*10 + c-'0' ;
    return k*f ;
}
int n, m ; int a[N], hh[N], gg[N] ;
deque<int>q1 ; // 递减序列维护最大值 
deque<int>q2 ; // 递增序列维护最小值 
deque<int>q11 ; // 维护递增序列的值在数组中的下标 
deque<int>q22 ; // 维护递减序列的值在数组中的下标 

int main() {
    n = read(), m = read() ;
    for(int i=1;i<=n;i++) a[i] = read() ;
    for(int i=1;i<m;i++) {
        while(q1.size() && q1.back() <= a[i]) q1.pop_back(), q11.pop_back() ;
        while(q2.size() && q2.back() >= a[i]) q2.pop_back(), q22.pop_back() ;
        q1.push_back(a[i]), q2.push_back(a[i]) ;
        q11.push_back(i), q22.push_back(i) ;
    }
    int cnt = 0 ;
    for(int i=m;i<=n;i++) {
        while(q1.size() && q1.back() <= a[i]) q1.pop_back(), q11.pop_back() ;
        while(q2.size() && q2.back() >= a[i]) q2.pop_back(), q22.pop_back() ;
        q1.push_back(a[i]), q2.push_back(a[i]) ; q11.push_back(i), q22.push_back(i) ;
         while(q11.front() <= i-m) q1.pop_front(), q11.pop_front() ;
        while(q22.front() <= i-m) q2.pop_front(), q22.pop_front() ;
        hh[++cnt] = q1.front(), gg[cnt] = q2.front() ;
    }
    for(int i=1;i<=cnt;i++) printf("%d ",gg[i]) ; printf("\n") ;
    for(int i=1;i<=cnt;i++) printf("%d ",hh[i]) ;
    return 0 ;
}
View Code

 

 update :

  之前的代码有些麻烦了,更简洁的代码请看这里:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 const int N = 1e6 + 10 ;
 8 
 9 inline int read() {
10     int k = 0 , f = 1 ; char c = getchar() ;
11     for( ; !isdigit(c) ; c = getchar())
12       if(c == '-') f = -1 ;
13     for( ; isdigit(c) ; c = getchar())
14       k = k*10 + c-'0' ;
15     return k*f ;
16 }
17 int n, m ;  
18 int hh[N], q1[N], q2[N], a1[N], a2[N] ;   // 单调递增维护最小值,单调递减维护最大值  ( 都维护序号 
19 
20 int main() {
21     n = read(), m = read() ;  int h1 = 1, h2 = 1, t1 = 0, t2 = 0 ;
22     for(int i=1;i<=n;i++) hh[i] = read() ;
23     for(int i=1;i<=m;i++) {
24         while(h1 <= t1 && hh[q1[t1]] >= hh[i]) t1-- ;
25         q1[++t1] = i ;
26         while(h2 <= t2 && hh[q2[t2]] <= hh[i]) t2-- ;
27         q2[++t2] = i ;
28     }
29     int tot = 0 ;  a1[++tot] = hh[q1[h1]], a2[tot] = hh[q2[h2]] ;
30     for(int i=m+1;i<=n;i++) {
31         while(h1 <= t1 && hh[q1[t1]] >= hh[i]) t1-- ;  q1[++t1] = i ;
32         while(q1[h1] <= i-m) h1++ ;
33         while(h2 <= t2 && hh[q2[t2]] <= hh[i]) t2-- ;  q2[++t2] = i ;
34         while(q2[h2] <= i-m) h2++ ;
35         a1[++tot] = hh[q1[h1]], a2[tot] = hh[q2[h2]] ;
36     }
37     for(int i=1;i<=tot;i++) printf("%d ",a1[i]) ; printf("\n") ;
38     for(int i=1;i<=tot;i++) printf("%d ",a2[i]) ;
39     return 0 ;
40 }

 

posted @ 2018-03-14 15:42  zubizakeli  阅读(196)  评论(0编辑  收藏  举报