題目描述
現在有一堆數字共N個數字(N<=10^6),以及一個大小為k的視窗。現在這個從左邊開始向右滑動,每次滑動一個機關,求出每次滑動後視窗中的最大值和最小值。
例如:
The array is [1 3 -1 -3 5 3 6 7], and k = 3.
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CMygzM3QGO5gjN1ETYldDZ5YzN5YmYlVTYzMmN5MjYm9CX5EzLcVDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL1M3Lc9CX6MHc0RHaiojIsJye.png)
輸入輸出格式
輸入格式:
輸入一共有兩行,第一行為n,k。
第二行為n個數(<INT_MAX).
輸出格式:
輸出共兩行,第一行為每次視窗滑動的最小值
第二行為每次視窗滑動的最大值
輸入輸出樣例
輸入樣例#1:
8 3
1 3 -1 -3 5 3 6 7
輸出樣例#1:
-1 -3 -3 -3 3 3
3 3 5 5 6 7
說明
50%的資料,n<=10^5
100%的資料,n<=10^6
Solution:
本題是單調隊列的模闆題。。。
單調隊列思想雖簡單,但是代碼各種判斷很容易出錯,于是打了一個線段樹水一波分。
思路就是區間查詢最值,維護一下就$OK$了。
代碼:
#include<bits/stdc++.h>
#define il inline
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int inf=2147483647,N=1e6+7;
using namespace std;
int n,k,cnt,ans1[N],ans2[N];
struct node{
int maxn,minn;
}tr[N<<2];
il int gi(){
int a=0;char x=getchar();bool f=0;
while((x<'0'||x>'9')&&x!='-')x=getchar();
if(x=='-')x=getchar(),f=1;
while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
return f?-a:a;
}
il int Max(int a,int b){return a>b?a:b;}
il int Min(int a,int b){return a>b?b:a;}
il void pushup(int rt){
tr[rt].maxn=Max(tr[rt<<1].maxn,tr[rt<<1|1].maxn);
tr[rt].minn=Min(tr[rt<<1].minn,tr[rt<<1|1].minn);
}
il void build(int l,int r,int rt){
if(l==r){tr[rt].maxn=tr[rt].minn=gi();return;}
int m=l+r>>1;
build(lson),build(rson);
pushup(rt);
}
il void query(int L,int R,int l,int r,int rt,int cnt){
if(L<=l&&R>=r){ans1[cnt]=Min(ans1[cnt],tr[rt].minn);ans2[cnt]=Max(ans2[cnt],tr[rt].maxn);return;}
int m=l+r>>1;
if(L<=m)query(L,R,lson,cnt);
if(R>m)query(L,R,rson,cnt);
}
int main(){
n=gi(),k=gi()-1;
for(int i=1;i<=n;i++)ans1[i]=inf,ans2[i]=-inf;
build(1,n,1);
for(int i=1;i+k<=n;i++)query(i,i+k,1,n,1,++cnt);
for(int i=1;i<=cnt;i++)printf("%d ",ans1[i]);
printf("\n");
for(int i=1;i<=cnt;i++)printf("%d ",ans2[i]);
return 0;
}