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("\n");
79         for(int i=k; i<=n; i++)
80         {
81             if(i!=k) printf(" ");
82             printf("%d",maxx[i]);
83         }
84         printf("\n");
85 
86     }
87     return 0;
88 }
View Code

 

 

posted @ 2014-03-20 22:11  byluoluo  阅读(253)  评论(0编辑  收藏  举报