★☆ 输入文件:window.in
输出文件:window.out
简单对比
时间限制:2 s 内存限制:256 MB
【问题描述】
给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表:
Window position | Min value | Max value |
[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 |
你的任务是找出窗口在各位置时的max value,min value.
输入格式:
第一行n,k,第二行为长度为n的数组
输出格式:
第一行每个位置的min value,第二行每个位置的max value
样例
:
window.in
8 3
1 3 -1 -3 5 3 6 7
window.out
-1 -3 -3 -3 3 3
3 3 5 5 6 7
数据范围:
20%:n≤500; 50%:n≤100000;
100%:n≤1000000;
线段树
RMQ
#include <cstdio> #define Max 1000000 int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a>b?b:a; } struct NodeTypeTree{ int l,r,dis,max_value,min_value; }; struct NodeTypeTree tr[Max<<2]; struct Node { int a,b; }ans[Max]; int n,k,cnt; void tree_up(int k) { tr[k].max_value=max(tr[k<<1].max_value,tr[k<<1|1].max_value); tr[k].min_value=min(tr[k<<1].min_value,tr[k<<1|1].min_value); } void build(int k,int l,int r) { tr[k].l=l;tr[k].r=r; if(l==r) { scanf("%d",&tr[k].dis); tr[k].max_value=tr[k].dis; tr[k].min_value=tr[k].dis; return; } int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); tree_up(k); } void section_query(int k,int l,int r) { if(tr[k].l==l&&tr[k].r==r) { ans[cnt].a=max(ans[cnt].a,tr[k].max_value); ans[cnt].b=min(ans[cnt].b,tr[k].min_value); return; } int mid=(tr[k].l+tr[k].r)>>1; if(l>mid) section_query(k<<1|1,l,r); else if(r<=mid) section_query(k<<1,l,r); else section_query(k<<1,l,mid),section_query(k<<1|1,mid+1,r); } void swap(int &x,int &y) { int tmp=x; x=y; y=tmp; } int main() { freopen("window.in","r",stdin); freopen("window.out","w",stdout); scanf("%d%d",&n,&k); build(1,1,n); for(int i=1;i<=n-k+1;++i) { cnt++; ans[cnt].a=-0x7ffffff;ans[cnt].b=0x7fffffff; int x=i,y=i+k-1; if(x>y) swap(x,y); section_query(1,x,y); } for(int i=1;i<=cnt;++i) printf("%d ",ans[i].b); printf("\n"); for(int i=1;i<=cnt;++i) printf("%d ",ans[i].a); return 0; }