理解题意:给定一个数列和窗口范围k,求依次向右移动窗口时每次窗口内的最大和最小值。
没什么思维难度,普及+/提高的标签纯粹是吓唬人的,一边扫过去,用两个数组maxx和minn记录每个窗口内的最大最小值,移动过程中用两个变量L和R记录窗口的左右端点,然后判断滑动窗口时最大最小值是否被移出窗口,进入窗口的值是否大于当前最大值或小于当前最小值,做完后L++,R++,用while循环控制轻松水过这题。当然,如果数据比较极端故意卡时就可能没这么轻松了。(不过我估计也不太可能会有什么题目出这么可怕的数据)
下面是AC代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define N 1000010 #define ll long long using namespace std; const ll inf=9999999999; ll n,k,a[N],maxx[N],minn[N]; void ready() { cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i]; } void work() { ll l=1,r=k,cnt=0; ll mx=-inf,mn=inf; for(int i=l;i<=r;i++){ mx=max(mx,a[i]); mn=min(mn,a[i]); } maxx[++cnt]=mx; minn[cnt]=mn; l++;r++; while(r<=n){ if(a[l-1]==mx){ mx=-inf; for(int i=l;i<=r;i++) mx=max(mx,a[i]);} if(a[l-1]==mn){ mn=inf; for(int i=l;i<=r;i++) mn=min(mn,a[i]);} if(a[r]>mx)mx=a[r]; if(a[r]<mn)mn=a[r]; maxx[++cnt]=mx; minn[cnt]=mn; l++;r++; } for(int i=1;i<=cnt;i++) cout<<minn[i]<<" "; cout<<endl; for(int i=1;i<=cnt;i++) cout<<maxx[i]<<" "; } int main() { //freopen("water.in","r",stdin); std::ios::sync_with_stdio(false); ready();work();return 0; }
当然,滑动窗口在其他很多算法中都会用到,所以很有必要掌握好。
时间: 2024-10-11 02:37:39