队列,从一头进入,从另一头删除的数据结构。
第一步:初始化
|_|
|_|
|_|
|_|
|_|
|_| t=h=0
第二步:从队尾加入一个元素8
|_|
|_|
|_|
|_|
|8| t=1
|_| h=0
第三步:从队尾删除一个元素
|_|
|_|
|_|
|_|
|8|
|_| t=h=0
在这里虽然8仍然存在,但是由于t=0,所以下次如果在加入一个元素会将其覆盖掉,所以我们认为t--,就是对数据的删除
队列的典型的题目是:poj 2823 http://poj.org/problem?id=2823
代码如下:
#include <stdio.h> #include <string.h> #include <iostream> using namespace std; #define N 1000010 struct node{ int m, d; }Inc[N], Dec[N]; int mi[N], mx[N], k; bool cmpMAX(const int &a, const int &b){ return a>b; } bool cmpMIN(const int &a, const int &b){ return a<b; } void chk(int i, int &head, int &tail, node c[], bool cmp(const int &a, const int &b), int num) { //添加新节点到队尾,并删掉过期的头节点 while(tail >= head && cmp(c[tail].m, num)) tail--; c[++tail].m = num; c[tail].d = i; while(cmpMAX(i-c[head].d+1, k)) head++;//更新了一下head,如果保存的不在可视框内,则不应该考虑,否则wa } void solve() { int n, i, j, id=0, num; int head_I=0, tail_I=0, head_D=0, tail_D=0; scanf("%d%d", &n, &k); if(n>0 && k>=1) //初始化化队列里的第一个点 { scanf("%d", &num); Inc[0].m = Dec[0].m = num; Inc[0].d = Dec[0].d = 0; } for(i=1; i<k; i++) //初始化视窗中的点: 加入队列 { scanf("%d", &num); chk(i, head_I, tail_I, Inc, cmpMIN, num); chk(i, head_D, tail_D, Dec, cmpMAX, num); } mi[id] = Inc[head_I].m; mx[id++] = Dec[head_D].m; for(; i<n; i++) //添加并更新 { scanf("%d", &num); chk(i, head_I, tail_I, Inc, cmpMIN, num); chk(i, head_D, tail_D, Dec, cmpMAX, num); mi[id] = Inc[head_I].m; mx[id++] = Dec[head_D].m; } printf("%d", mx[0]); for(i=1; i<id; i++) printf(" %d", mx[i]); printf("\n%d", mi[0]); for(i=1; i<id; i++) printf(" %d", mi[i]); printf("\n"); } int main() { solve(); return 0; }