admin 管理员组

文章数量: 887021

windo

windo

题目描述:

给你一个长度为 N 的数组,一个长为 K 的滑动的窗体从最左移至最右端,
你只能见到窗口的K个数,每次窗体向右移动一位,如下表: 

Windo position                Min value   Maxvalue

[ 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. 

输入格式:

第 1 行n,k,
第 2 行为长度为 n 的数组 

输出格式:

2 行,
第 1 行每个位置的 min value,
第 2 行每个位置的 max value 

样例输入:

8  3

1  3  -1  -3 5  3  6  7

样例输出:

-1  -3  -3  -3  3  3

3  3  5  5  6  7

数据范围:

20%: n<=500;  
50%:  n<=100000; 
100%:  n<=1000000; 

k<=n;

 时间限制:

三秒(表示程序两秒就能过)


嗯…当我做这道题的时候,lzh学长告诉我这道题是要用单调队列做的…当时还没有学单调队列。然而在于我不信邪,偏要用数组做。//不能多次测试的时候别学我

 嗯...偏偏在于我真的试出来了,最开始没有优化的时候过了五组。优化了一下,九组,当时耗时还是3秒,最后的优化终于过而且不到两秒。

嗯...前面废话请自行省略...我只是过来表达一下激动的心情。好了下面上代码:

最初:

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int nn[1000100],mn[1000100]={},mx[1000100]={};
int main()
{/*freopen("00.in","r",stdin);freopen("00.out","w",stdout);*/int n,k;cin>>n>>k;for(int i=1;i<=n;i++) cin>>nn[i];for(int i=1;i<=n-k+1;i++){int maxx=-10000000,minn=10000000;for(int j=i;j<i+k;j++){if(nn[j]>maxx)maxx=nn[j];if(nn[j]<minn)minn=nn[j];}mn[i]=minn; mx[i]=maxx;}for(int i=1;i<=n-k+1;i++) cout<<mn[i]<<' ';cout<<endl;for(int i=1;i<=n-k+1;i++) cout<<mx[i]<<' ';return 0;
}
第一次优化:

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int nn[1000100],mn[1000100]={},mx[1000100]={};
int main()
{/*freopen("00.in","r",stdin);freopen("00.out","w",stdout);*/int n,k;cin>>n>>k;for(int i=1;i<=n;i++) cin>>nn[i];int maxx=-10000000,minn=10000000;for(int i=1;i<=k;i++){if(nn[i]>maxx)maxx=nn[i];if(nn[i]<minn)minn=nn[i];}mn[1]=minn; mx[1]=maxx;for(int i=2;i<=n-k+1;i++){if((maxx==nn[i-1])||(minn==nn[i-1])){maxx=-10000000,minn=10000000;if(maxx<nn[i-1+k]) maxx=nn[i-1+k];if(minn>nn[i-1+k]) minn=nn[i-1+k];for(int j=i;j<i+k;j++){if(nn[j]>maxx)maxx=nn[j];if(nn[j]<minn)minn=nn[j];}}else{if(maxx<nn[i-1+k]) maxx=nn[i-1+k];if(minn>nn[i-1+k]) minn=nn[i-1+k];}mn[i]=minn; mx[i]=maxx;}for(int i=1;i<=n-k+1;i++) cout<<mn[i]<<' ';cout<<endl;for(int i=1;i<=n-k+1;i++) cout<<mx[i]<<' ';return 0;
}
最终优化:

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int nn[1000100],mn[1000100]={},mx[1000100]={};
int main()
{/*freopen("00.in","r",stdin);freopen("00.out","w",stdout);*/std::ios::sync_with_stdio(false);int n,k;cin>>n>>k;for(int i=1;i<=n;i++) cin>>nn[i];int maxx=-10000000,minn=10000000;for(int i=1;i<=k;i++){if(nn[i]>maxx)maxx=nn[i];if(nn[i]<minn)minn=nn[i];}mn[1]=minn; mx[1]=maxx;for(int i=2;i<=n-k+1;i++){if((maxx==nn[i-1])||(minn==nn[i-1])){maxx=-10000000,minn=10000000;if(maxx<nn[i-1+k]) maxx=nn[i-1+k];if(minn>nn[i-1+k]) minn=nn[i-1+k];for(int j=i;j<i+k;j++){if(nn[j]>maxx)maxx=nn[j];if(nn[j]<minn)minn=nn[j];}}else{if(maxx<nn[i-1+k]) maxx=nn[i-1+k];if(minn>nn[i-1+k]) minn=nn[i-1+k];}mn[i]=minn; mx[i]=maxx;}for(int i=1;i<=n-k+1;i++) cout<<mn[i]<<' ';cout<<endl;for(int i=1;i<=n-k+1;i++) cout<<mx[i]<<' ';return 0;
}


其实看了会发现第二次与最后一次只差了一点,强烈推荐一个好用的东西:

std::ios::sync_with_stdio(false);

可以去百度一下这是什么。效率特别高,别问我为什么,我也不知道。


好了接下来来说一下我的思路,最初始的,也就是搜索,一次一次搜。


改过之后的也就是先判断每次去掉的是不是最大或最小,不是什么都好说,看新增进来的有没有比最大的大或者比最小的小。没有的话还是在数组里存原来的最大最小。有的话那也就是赋值再存。

但是当去掉的是最大或者最小的时候,再查找一遍(这里应该是可以优化的,但是怪我有点懒)。

最后输出。就这样。

本文标签: windo