zoukankan      html  css  js  c++  java
  • 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("
    ") ;
        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("
    ") ;
    38     for(int i=1;i<=tot;i++) printf("%d ",a2[i]) ;
    39     return 0 ;
    40 }
  • 相关阅读:
    GIT分支的一些开发心得
    java文件压缩和解压
    java发送邮件
    单例多例
    String,StringBuffer,StringBuilder区别
    GIT文件的三种状态
    javascript 常用技巧
    javascript优化工具 Doloto
    thinkphp 5内置验证规则-基本版
    php+redis配置
  • 原文地址:https://www.cnblogs.com/zub23333/p/8568040.html
Copyright © 2011-2022 走看看