题解(单调队列模板) 2018寒假训练1 B.区间最小最大值

zhouwc

2018-02-25 09:49:27

Personal

问题 B: 区间最小最大值 时间限制: 2 Sec 内存限制: 128 MB [提交][状态][讨论版] 题目描述 给定n个元素,以及一个正整数w,求每段区间的最小最大值。这些区间为:[1,1+w-1], [2,2+w-1], ..., [n-w+1,n]。 例如8个元素为[1 3 -1 -3 5 3 6 7], w为3,那么有下列最小最大值: 区间 最小值 最大值 [1 3 -1] -3 5 3 6 7 -1 3 1 [3 -1 -3] 5 3 6 7 -3 3 1 3 [-1 -3 5] 3 6 7 -3 5 1 3 -1 [-3 5 3] 6 7 -3 5 1 3 -1 -3 [5 3 6] 7 3 6 1 3 -1 -3 5 [3 6 7] 3 7 输入 第一行输入n,w 第二行输入n个整数 输出 第一行输出区间最小值 第二行输出区间最大值 样例输入 8 3 1 3 -1 -3 5 3 6 7 样例输出 -1 -3 -3 -3 3 3 3 3 5 5 6 7 提示 1<=n<=10^6 1<=w<=n 10^-9 <= 元素 <= 10^9 题解 这题是单调队列。分别维护队首和队尾。 罗老师核心代码 ```cpp id队列存储下标 Q队列存储值 void minquery(){ //求最小值 int st=0, ed=0; for(int i=1; i<=w; i++){ //先扫描到w,产生初始单调队列 while(st<ed && Q[ed]>a[i]) ed--; ed++; Q[ed]=a[i]; id[ed]=i; } for(int i=w+1; i<=n; i++){ while(st<ed && id[st+1]<i-w) st++; //维护队首 printf("%d ",Q[st+1]); while(st<ed && Q[ed]>a[i]) ed--; //维护队尾 ed++; Q[ed]=a[i]; id[ed]=i; } while(st<ed && id[st+1]<n+1-w) st++; printf("%d\n",Q[st+1]); } ``` 我的代码 ```cpp #include<stdio.h> #include<cstring> #include<algorithm> using namespace std; int f[1000005],head,tail,n,m,a[1000005]; int min() { head=1; tail=0; for (int i=1;i<=n;i++) { while(head<=tail&&f[head]+m<=i) head++; while(head<=tail&&a[i]<a[f[tail]]) tail--; f[++tail]=i; if(i>=m) printf("%d",a[f[head]]); if (i!=n&&i>=m) printf(" "); } printf("\n"); return 0; } int max() { head=1; tail=0; memset(f,0,sizeof(f)); for (int i=1;i<=n;i++) { while(head<=tail&&f[head]+m<=i) head++; while(head<=tail&&a[i]>a[f[tail]]) tail--; f[++tail]=i; if(i>=m) printf("%d",a[f[head]]); if (i!=n&&i>=m) printf(" "); } return 0; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); min(); max(); } ```