【重做】滑动窗口(单调队列)
没什么特殊的,与以前的相比会条理一些吧。
1 #include<bits/stdc++.h> 2 #define rep(i,a,n) for(register int i = a;i <= n;++i) 3 #define per(i,n,a) for(register int i = n;i <= a;--i) 4 using namespace std; 5 typedef long long ll; 6 7 const int Maxn = 1e6+10; 8 9 ll read(){ 10 ll a = 0;char c = getchar(),l = c; 11 while(c < '0'||c > '9')l = c,c = getchar(); 12 while('0' <= c&&c <= '9')a = a*10+c-'0',c = getchar(); 13 if(l == '-')return -a;return a; 14 } 15 16 int n,k,ta,he,x; 17 int a[Maxn]; 18 int qx[Maxn],qp[Maxn]; 19 20 int main(){ 21 n = read(),k = read(); 22 rep(i,1,n)a[i] = read(); 23 24 ta = he = Maxn>>1; 25 rep(i,1,n){ 26 x = a[i]; 27 while(ta <= he) 28 if(qx[ta] > x){if(++ta >= Maxn)ta = 0;} 29 else break; 30 while(ta <= he) 31 if(i-qp[he] >= k){if(--he < 0)he = Maxn-1;} 32 else break; 33 if(--ta < 0)ta = Maxn-1; 34 qx[ta] = x,qp[ta] = i; 35 if(i >= k)printf("%d ",qx[he]); 36 } 37 puts(""); 38 39 ta = he = Maxn>>1; 40 rep(i,1,n){ 41 x = a[i]; 42 while(ta <= he) 43 if(qx[ta] < x){if(++ta >= Maxn)ta = 0;} 44 else break; 45 while(ta <= he) 46 if(i-qp[he] >= k){if(--he < 0)he = Maxn-1;} 47 else break; 48 if(--ta < 0)ta = Maxn-1; 49 qx[ta] = x,qp[ta] = i; 50 if(i >= k)printf("%d ",qx[he]); 51 } 52 53 return 0; 54 }
2020 12 2
受另一道题目的启发又想出了一种写法,实际上并不需要开循环队列,因为队首的移动方向是单一的。
1 int qx[Maxn],qi[Maxn],a[Maxn]; 2 int n,m,he,ta; 3 4 int main(){ 5 n = read(),m = read(); 6 rep(i,1,n)a[i] = read(); 7 8 he = 0,ta = -1; 9 rep(i,1,n){ 10 while(he <= ta&&qx[ta] >= a[i])ta--; 11 qx[++ta] = a[i],qi[ta] = i; 12 while(he <= ta&&qi[he] <= i-m)he++; 13 if(i >= m)printf("%d ",qx[he]); 14 } 15 puts(""); 16 17 he = 0,ta = -1; 18 rep(i,1,n){ 19 while(he <= ta&&qx[ta] <= a[i])ta--; 20 qx[++ta] = a[i],qi[ta] = i; 21 while(he <= ta&&qi[he] <= i-m)he++; 22 if(i >= m)printf("%d ",qx[he]); 23 } 24 25 return 0; 26 }