其实可以用线段树来做..
这道题的具体做法就是维护一个数组
队头s和队尾t。
我们需要维护两个东西,第一个是单调性,第二个是长度。
我们每次加入一个新值,我们是放到尾部。
这个时候我们维护单调性,从尾部开始把大于当前值的全部删除,反正我们找的是最小值,所以不影响。
之后处理完单调性后我们把新值插入。
插入新值后我们形成了新的滑动区间,记录一下最小元素,也就是队伍头部的元素。
之后我们要处理长度问题。看看当前队伍头部的那个值的位置是否已经出去了,就是已经超出滑动区间了,如果
超出了,我们s++即可。如果没有我们就不用管。
重复这个过程即可
//http://blog.csdn.net/waduan2/article/details/52416523代码
- #include<cstring>
- #include<cstdio>
- #define N 1000050
- #define INF 2147483647
- using namespace std;
- int n,k;
- int a[N];
- struct Elem{
- int k,num;
- }Queue[N];
- int l=1,r=1;
- inline void GetMin(){
- memset(Queue,0,sizeof Queue);
- Queue[0].k=-INF;
- l=1,r=1;
- for(int i=1;i<=k;i++){
- while(Queue[r].k>=a[i] && r>=l) r--;
- Queue[++r].k=a[i];
- Queue[r].num=i;
- }
- for(int i=k;i<=n;i++){
- while(Queue[r].k>=a[i] && r>=l) r--; //维护单调性
- Queue[++r].k=a[i];
- Queue[r].num=i;
- while(Queue[l].num<=i-k) l++; //维护队列下标范围k以内
- printf("%d ",Queue[l].k);
- }
- }
- inline void GetMax(){
- memset(Queue,0,sizeof Queue);
- Queue[0].k=INF;
- l=1,r=1;
- for(int i=1;i<=k;i++){
- while(Queue[r].k<=a[i] && r>=l) r--;
- Queue[++r].k=a[i];
- Queue[r].num=i;
- }
- for(int i=k;i<=n;i++){
- while(Queue[r].k<=a[i] && r>=l) r--;
- Queue[++r].k=a[i];
- Queue[r].num=i;
- while(Queue[l].num<=i-k) l++;
- printf("%d ",Queue[l].k);
- }
- }
- int main(){
- scanf("%d%d",&n,&k);
- for(int i=1;i<=n;i++)
- scanf("%d",a+i);
- GetMin();
- printf("\n");
- GetMax();
- return 0;
- }