zoukankan      html  css  js  c++  java
  • poj 2823 Sliding Window (单调队列)

    初步学习了下单调队列,一个比较简单的数据结构,即队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队操作。

    详见 http://blog.csdn.net/code_pang/article/details/14104151

    题意:给出n(n<=1000000)个数字的序列和整数k,其中k为一个窗口的长度,窗口开始在序列的最左,每次右移一次,问每次窗口内的最大最小值。

    思路:

    维护两个单调队列,分别用于查询最大最小值。

    其中一个单调递增,插入元素x时找到第一个比x小的元素,在它右边插入x,删除x后面所有元素。

    同时由于窗口的移动,每个元素都有时效性,插入x比x小但时效性已过的也一并删除。

    查询操作则是从队首找出第一元素,在窗口内则为结果,若已失去时效性,则删去,然后继续往后找。

    插入操作还可以用二分优化。

     1 #include <cstdio>
     2 #include <cstring>
     3 #define N 1000005
     4 
     5 struct Que
     6 {
     7     int i, x; //x为加入序号
     8 }q1[N],q2[N];
     9 int front1, front2, tail1, tail2;
    10 int minx[N], maxx[N], n, k;
    11 
    12 //递增找最小
    13 void add1(int i, int x)
    14 {
    15     while(front1<=tail1)
    16     {
    17         if(i < q1[tail1].i+k && q1[tail1].x < x)
    18             break;
    19         tail1--;
    20     }
    21     q1[++tail1].x = x;
    22     q1[tail1].i = i;
    23 }
    24 
    25 //递减找最大
    26 void add2(int i, int x)
    27 {
    28     while(front2<=tail2)
    29     {
    30         if(i < q2[tail2].i+k && q2[tail2].x > x)
    31             break;
    32         tail2--;
    33     }
    34     q2[++tail2].x = x;
    35     q2[tail2].i = i;
    36 }
    37 
    38 int query1(int i)
    39 {
    40     while(front1<=tail1 && i >= q1[front1].i+k)
    41         front1++;
    42     return q1[front1].x;
    43 }
    44 
    45 int query2(int i)
    46 {
    47     while(front2<=tail2 && i >= q2[front2].i+k)
    48         front2++;
    49     return q2[front2].x;
    50 }
    51 
    52 int main()
    53 {
    54     while(scanf("%d%d",&n,&k)!=EOF)
    55     {
    56         front1 = 0; tail1 = -1;
    57         front2 = 0; tail2 = -1;
    58         int x;
    59         for(int i=1; i<=k-1; i++)
    60         {
    61             scanf("%d",&x);
    62             add1(i, x);
    63             add2(i, x);
    64         }
    65         for(int i=k; i<=n; i++)
    66         {
    67             scanf("%d",&x);
    68             add1(i, x);
    69             add2(i, x);
    70             minx[i] = query1(i);
    71             maxx[i] = query2(i);
    72         }
    73         for(int i=k; i<=n; i++)
    74         {
    75             if(i!=k) printf(" ");
    76             printf("%d",minx[i]);
    77         }
    78         printf(" ");
    79         for(int i=k; i<=n; i++)
    80         {
    81             if(i!=k) printf(" ");
    82             printf("%d",maxx[i]);
    83         }
    84         printf(" ");
    85 
    86     }
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    计算任意两个日期的间隔天数
    题目标题: 排它平方数
    历届试题 剪格子
    历届试题 翻硬币
    C语言中%d,%o,%f,%e,%x的意义
    历届试题 买不到的数目
    九度 OJ1008 hdu 3790
    南洋理工 OJ 115 城市平乱 dijstra算法
    蓝桥杯 错误票据 原创代码+思路
    历届试题 连号区间数
  • 原文地址:https://www.cnblogs.com/byluoluo/p/3614772.html
Copyright © 2011-2022 走看看